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 2019/03/07 23:49:24 UTC

[impala] 02/05: IMPALA-7917 (Part 2): Decouple Sentry from Impala

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

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

commit b32ca155ea463187bdee87e74039d3dcd2681603
Author: Fredy Wijaya <fw...@cloudera.com>
AuthorDate: Wed Feb 20 17:25:08 2019 -0600

    IMPALA-7917 (Part 2): Decouple Sentry from Impala
    
    This patch adds a new flag --authorization_factory_class and creates
    some factories to make it easier to switch to a different authorization
    provider. For backward compatability the default authorization provider
    is still set to Sentry.
    
    The --authorization_factory_class is used to specify which authorization
    provider implementation to use.
    
    This patch has no functional change.
    
    Testing:
    - Ran all FE tests
    - Ran all authorization E2E tests
    
    Change-Id: I051d06451fb14ba2ffb3f7e0d4aae37dee55ab86
    Reviewed-on: http://gerrit.cloudera.org:8080/12542
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/service/frontend.cc                         |   5 +-
 be/src/util/backend-gflag-util.cc                  |   2 +
 common/thrift/BackendGflags.thrift                 |   2 +
 .../org/apache/impala/analysis/AdminFnStmt.java    |  10 +-
 .../impala/analysis/AlterDbSetOwnerStmt.java       |   2 +-
 .../analysis/AlterTableOrViewSetOwnerStmt.java     |   2 +-
 .../analysis/AlterTableSetTblProperties.java       |  10 +-
 .../apache/impala/analysis/AnalysisContext.java    |   9 +-
 .../java/org/apache/impala/analysis/Analyzer.java  | 120 ++++++++++++---------
 .../apache/impala/analysis/AuthorizationStmt.java  |   8 +-
 .../apache/impala/analysis/CollectionTableRef.java |  10 +-
 .../apache/impala/analysis/CopyTestCaseStmt.java   |  11 +-
 .../impala/analysis/CreateFunctionStmtBase.java    |   8 +-
 .../impala/analysis/CreateTableAsSelectStmt.java   |   2 +-
 .../apache/impala/analysis/CreateTableStmt.java    |  10 +-
 .../apache/impala/analysis/DescribeTableStmt.java  |  22 ++--
 .../apache/impala/analysis/DropFunctionStmt.java   |   8 +-
 .../java/org/apache/impala/analysis/HdfsUri.java   |   7 +-
 .../org/apache/impala/analysis/InsertStmt.java     |   8 +-
 .../apache/impala/analysis/ResetMetadataStmt.java  |  28 +++--
 .../impala/authorization/AuthorizableColumn.java   |  57 ++++++++++
 ...horizationProvider.java => AuthorizableDb.java} |  24 ++++-
 .../impala/authorization/AuthorizableFactory.java  |  70 ++++++++++++
 ...horizationProvider.java => AuthorizableFn.java} |  30 +++++-
 ...zationProvider.java => AuthorizableServer.java} |  17 ++-
 ...izationProvider.java => AuthorizableTable.java} |  33 +++++-
 ...orizationProvider.java => AuthorizableUri.java} |  21 +++-
 .../impala/authorization/AuthorizationChecker.java |  34 +++---
 .../impala/authorization/AuthorizationFactory.java |  57 ++++++++++
 .../impala/authorization/AuthorizationPolicy.java  |   6 +-
 .../authorization/AuthorizationProvider.java       |   3 +-
 .../authorization/DefaultAuthorizableFactory.java  |  79 ++++++++++++++
 .../authorization/NoneAuthorizationFactory.java    |  74 +++++++++++++
 .../authorization/PrivilegeRequestBuilder.java     |  50 ++++-----
 .../sentry/SentryAuthorizableFactory.java          |  79 ++++++++++++++
 .../sentry/SentryAuthorizationChecker.java         |  15 +--
 .../sentry/SentryAuthorizationConfig.java          |   7 --
 .../sentry/SentryAuthorizationFactory.java         |  87 +++++++++++++++
 .../org/apache/impala/service/BackendConfig.java   |   4 +
 .../java/org/apache/impala/service/Frontend.java   |  74 +++++++------
 .../java/org/apache/impala/service/JniCatalog.java |  35 ++++--
 .../org/apache/impala/service/JniFrontend.java     |  41 ++++---
 .../impala/analysis/AnalyzeAuthStmtsTest.java      |  10 +-
 .../org/apache/impala/analysis/AuditingTest.java   |   3 +-
 .../impala/analysis/AuthorizationStmtTest.java     |  52 +++++----
 .../apache/impala/analysis/AuthorizationTest.java  |  16 +--
 .../impala/analysis/StmtMetadataLoaderTest.java    |   8 +-
 .../org/apache/impala/common/FrontendFixture.java  |  25 +++--
 .../org/apache/impala/common/FrontendTestBase.java |   5 +
 .../org/apache/impala/common/QueryFixture.java     |   5 +-
 .../apache/impala/testutil/ImpaladTestCatalog.java |   8 +-
 .../impala/testutil/PlannerTestCaseLoader.java     |   6 +-
 52 files changed, 1002 insertions(+), 317 deletions(-)

diff --git a/be/src/service/frontend.cc b/be/src/service/frontend.cc
index c4ad4c7..1df77d4 100644
--- a/be/src/service/frontend.cc
+++ b/be/src/service/frontend.cc
@@ -37,6 +37,9 @@ using namespace impala;
 
 // Authorization related flags. Must be set to valid values to properly configure
 // authorization.
+DEFINE_string(authorization_factory_class,
+    "org.apache.impala.authorization.sentry.SentryAuthorizationFactory",
+    "Specifies the class name that implements the authorization provider.");
 DEFINE_string(server_name, "", "The name to use for securing this impalad "
     "server during authorization. Set to enable authorization. By default, the "
     "authorization policy will be loaded from the catalog server (via the statestore)."
@@ -46,7 +49,7 @@ DEFINE_string(authorization_policy_file, "", "HDFS path to the authorization pol
     "read from a file.");
 DEFINE_string(authorization_policy_provider_class,
     "org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider",
-    "Advanced: The authorization policy provider class name.");
+    "Advanced: The authorization policy provider class name for Sentry.");
 DEFINE_string(authorized_proxy_user_config, "",
     "Specifies the set of authorized proxy users (users who can delegate to other "
     "users during authorization) and whom they are allowed to delegate. "
diff --git a/be/src/util/backend-gflag-util.cc b/be/src/util/backend-gflag-util.cc
index 0490288..07e2b9a 100644
--- a/be/src/util/backend-gflag-util.cc
+++ b/be/src/util/backend-gflag-util.cc
@@ -72,6 +72,7 @@ DECLARE_int64(exchg_node_buffer_size_bytes);
 DECLARE_int32(kudu_mutation_buffer_size);
 DECLARE_int32(kudu_error_buffer_size);
 DECLARE_int32(hms_event_polling_interval_s);
+DECLARE_string(authorization_factory_class);
 
 namespace impala {
 
@@ -143,6 +144,7 @@ Status GetThriftBackendGflags(JNIEnv* jni_env, jbyteArray* cfg_bytes) {
   cfg.__set_kudu_error_buffer_size(FLAGS_kudu_error_buffer_size);
   cfg.__set_hms_event_polling_interval_s(FLAGS_hms_event_polling_interval_s);
   cfg.__set_impala_build_version(::GetDaemonBuildVersion());
+  cfg.__set_authorization_factory_class(FLAGS_authorization_factory_class);
   RETURN_IF_ERROR(SerializeThriftMsg(jni_env, &cfg, cfg_bytes));
   return Status::OK();
 }
diff --git a/common/thrift/BackendGflags.thrift b/common/thrift/BackendGflags.thrift
index 98f9795..f252326 100644
--- a/common/thrift/BackendGflags.thrift
+++ b/common/thrift/BackendGflags.thrift
@@ -117,4 +117,6 @@ struct TBackendGflags {
   45: required i32 hms_event_polling_interval_s
 
   46: required string impala_build_version
+
+  47: required string authorization_factory_class
 }
diff --git a/fe/src/main/java/org/apache/impala/analysis/AdminFnStmt.java b/fe/src/main/java/org/apache/impala/analysis/AdminFnStmt.java
index fd7e4f9..cf131b2 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AdminFnStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AdminFnStmt.java
@@ -20,7 +20,7 @@ package org.apache.impala.analysis;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
+import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.common.AnalysisException;
 import org.apache.impala.common.InternalException;
 import org.apache.impala.common.Pair;
@@ -96,12 +96,12 @@ public class AdminFnStmt extends StatementBase {
    * shutdown('host:port'), shutdown(deadline), shutdown('host:port', deadline).
    */
   private void analyzeShutdown(Analyzer analyzer) throws AnalysisException {
-    if (analyzer.getAuthzConfig().isEnabled()) {
+    AuthorizationConfig authzConfig = analyzer.getAuthzConfig();
+    if (authzConfig.isEnabled()) {
       // Only admins (i.e. user with ALL privilege on server) can execute admin functions.
-      String authzServer = analyzer.getAuthzConfig().getServerName();
+      String authzServer = authzConfig.getServerName();
       Preconditions.checkNotNull(authzServer);
-      analyzer.registerPrivReq(
-          new PrivilegeRequestBuilder().onServer(authzServer).all().build());
+      analyzer.registerPrivReq(builder -> builder.onServer(authzServer).all().build());
     }
 
     // TODO: this parsing and type checking logic is specific to the command, similar to
diff --git a/fe/src/main/java/org/apache/impala/analysis/AlterDbSetOwnerStmt.java b/fe/src/main/java/org/apache/impala/analysis/AlterDbSetOwnerStmt.java
index e9ea71f..b430f34 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AlterDbSetOwnerStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AlterDbSetOwnerStmt.java
@@ -55,7 +55,7 @@ public class AlterDbSetOwnerStmt extends AlterDbStmt {
     // We don't allow assigning to a non-existent role because Sentry should know about
     // all roles. Sentry does not track all users so we allow assigning to a user
     // that Sentry doesn't know about yet.
-    if (analyzer.getAuthzConfig().isEnabled() && owner_.getOwnerType() == TOwnerType.ROLE
+    if (analyzer.isAuthzEnabled() && owner_.getOwnerType() == TOwnerType.ROLE
         && analyzer.getCatalog().getAuthPolicy().getRole(ownerName) == null) {
       throw new AnalysisException(String.format("Role '%s' does not exist.", ownerName));
     }
diff --git a/fe/src/main/java/org/apache/impala/analysis/AlterTableOrViewSetOwnerStmt.java b/fe/src/main/java/org/apache/impala/analysis/AlterTableOrViewSetOwnerStmt.java
index a11f849..6994f77 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AlterTableOrViewSetOwnerStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AlterTableOrViewSetOwnerStmt.java
@@ -52,7 +52,7 @@ public abstract class AlterTableOrViewSetOwnerStmt extends AlterTableStmt {
     // We don't allow assigning to a non-existent role because Sentry should know about
     // all roles. Sentry does not track all users so we allow assigning to a user
     // that Sentry doesn't know about yet.
-    if (analyzer.getAuthzConfig().isEnabled() && owner_.getOwnerType() == TOwnerType.ROLE
+    if (analyzer.isAuthzEnabled() && owner_.getOwnerType() == TOwnerType.ROLE
         && analyzer.getCatalog().getAuthPolicy().getRole(ownerName) == null) {
       throw new AnalysisException(String.format("Role '%s' does not exist.", ownerName));
     }
diff --git a/fe/src/main/java/org/apache/impala/analysis/AlterTableSetTblProperties.java b/fe/src/main/java/org/apache/impala/analysis/AlterTableSetTblProperties.java
index 12819a8..359e3ed 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AlterTableSetTblProperties.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AlterTableSetTblProperties.java
@@ -24,7 +24,7 @@ import java.util.Map;
 import org.apache.avro.SchemaParseException;
 import org.apache.hadoop.hive.metastore.api.hive_metastoreConstants;
 import org.apache.hadoop.hive.serde2.avro.AvroSerdeUtils;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
+import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.catalog.Column;
 import org.apache.impala.catalog.FeFsTable;
 import org.apache.impala.catalog.FeHBaseTable;
@@ -127,13 +127,13 @@ public class AlterTableSetTblProperties extends AlterTableSetStmt {
           String.format("Not allowed to set '%s' manually for managed Kudu tables .",
               KuduTable.KEY_TABLE_NAME));
     }
-    if (analyzer.getAuthzConfig().isEnabled()) {
+    AuthorizationConfig authzConfig = analyzer.getAuthzConfig();
+    if (authzConfig.isEnabled()) {
       if (keyForExternalProperty != null ||
           tblProperties_.containsKey(KuduTable.KEY_MASTER_HOSTS)) {
-        String authzServer = analyzer.getAuthzConfig().getServerName();
+        String authzServer = authzConfig.getServerName();
         Preconditions.checkNotNull(authzServer);
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder().onServer(
-            authzServer).all().build());
+        analyzer.registerPrivReq(builder -> builder.onServer(authzServer).all().build());
       }
     }
   }
diff --git a/fe/src/main/java/org/apache/impala/analysis/AnalysisContext.java b/fe/src/main/java/org/apache/impala/analysis/AnalysisContext.java
index cdbe791..e07d25f 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AnalysisContext.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AnalysisContext.java
@@ -29,6 +29,7 @@ import org.apache.impala.analysis.StmtMetadataLoader.StmtTableCache;
 import org.apache.impala.authorization.Authorizable;
 import org.apache.impala.authorization.AuthorizationChecker;
 import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationFactory;
 import org.apache.impala.authorization.Privilege;
 import org.apache.impala.authorization.PrivilegeRequest;
 import org.apache.impala.authorization.AuthorizationException;
@@ -60,7 +61,7 @@ import com.google.common.collect.Lists;
 public class AnalysisContext {
   private final static Logger LOG = LoggerFactory.getLogger(AnalysisContext.class);
   private final TQueryCtx queryCtx_;
-  private final AuthorizationConfig authzConfig_;
+  private final AuthorizationFactory authzFactory_;
   private final EventSequence timeline_;
 
   // Set in analyzeAndAuthorize().
@@ -70,10 +71,10 @@ public class AnalysisContext {
   // Use Hive's scheme for auto-generating column labels. Only used for testing.
   private boolean useHiveColLabels_;
 
-  public AnalysisContext(TQueryCtx queryCtx, AuthorizationConfig authzConfig,
+  public AnalysisContext(TQueryCtx queryCtx, AuthorizationFactory authzFactory,
       EventSequence timeline) {
     queryCtx_ = queryCtx;
-    authzConfig_ = authzConfig;
+    authzFactory_ = authzFactory;
     timeline_ = timeline;
   }
 
@@ -395,7 +396,7 @@ public class AnalysisContext {
   }
 
   public Analyzer createAnalyzer(StmtTableCache stmtTableCache) {
-    Analyzer result = new Analyzer(stmtTableCache, queryCtx_, authzConfig_);
+    Analyzer result = new Analyzer(stmtTableCache, queryCtx_, authzFactory_);
     result.setUseHiveColLabels(useHiveColLabels_);
     return result;
   }
diff --git a/fe/src/main/java/org/apache/impala/analysis/Analyzer.java b/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
index c1128ef..5fd2b73 100644
--- a/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
+++ b/fe/src/main/java/org/apache/impala/analysis/Analyzer.java
@@ -30,10 +30,12 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 
 import org.apache.impala.analysis.Path.PathType;
 import org.apache.impala.analysis.StmtMetadataLoader.StmtTableCache;
 import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationFactory;
 import org.apache.impala.authorization.Privilege;
 import org.apache.impala.authorization.PrivilegeRequest;
 import org.apache.impala.authorization.PrivilegeRequestBuilder;
@@ -193,7 +195,7 @@ public class Analyzer {
   // them properties of the tuple descriptor itself.
   private static class GlobalState {
     public final TQueryCtx queryCtx;
-    public final AuthorizationConfig authzConfig;
+    public final AuthorizationFactory authzFactory;
     public final DescriptorTable descTbl = new DescriptorTable();
     public final IdGenerator<ExprId> conjunctIdGenerator = ExprId.createGenerator();
     public final ColumnLineageGraph lineageGraph;
@@ -309,10 +311,10 @@ public class Analyzer {
     private final ExprRewriter exprRewriter_;
 
     public GlobalState(StmtTableCache stmtTableCache, TQueryCtx queryCtx,
-        AuthorizationConfig authzConfig) {
+        AuthorizationFactory authzFactory) {
       this.stmtTableCache = stmtTableCache;
       this.queryCtx = queryCtx;
-      this.authzConfig = authzConfig;
+      this.authzFactory = authzFactory;
       this.lineageGraph = new ColumnLineageGraph();
       List<ExprRewriteRule> rules = new ArrayList<>();
       // BetweenPredicates must be rewritten to be executable. Other non-essential
@@ -376,9 +378,9 @@ public class Analyzer {
   private boolean hasEmptySpjResultSet_ = false;
 
   public Analyzer(StmtTableCache stmtTableCache, TQueryCtx queryCtx,
-      AuthorizationConfig authzConfig) {
+      AuthorizationFactory authzFactory) {
     ancestors_ = new ArrayList<>();
-    globalState_ = new GlobalState(stmtTableCache, queryCtx, authzConfig);
+    globalState_ = new GlobalState(stmtTableCache, queryCtx, authzFactory);
     user_ = new User(TSessionStateUtil.getEffectiveUser(queryCtx.session));
   }
 
@@ -411,7 +413,7 @@ public class Analyzer {
    */
   public static Analyzer createWithNewGlobalState(Analyzer parentAnalyzer) {
     GlobalState globalState = new GlobalState(parentAnalyzer.globalState_.stmtTableCache,
-        parentAnalyzer.getQueryCtx(), parentAnalyzer.getAuthzConfig());
+        parentAnalyzer.getQueryCtx(), parentAnalyzer.getAuthzFactory());
     return new Analyzer(parentAnalyzer, globalState);
   }
 
@@ -566,21 +568,22 @@ public class Analyzer {
       // an analysis error. We should not accidentally reveal the non-existence of a
       // table/database if the user is not authorized.
       if (rawPath.size() > 1) {
-        PrivilegeRequestBuilder builder = new PrivilegeRequestBuilder()
-            .onTable(rawPath.get(0), rawPath.get(1))
-            .allOf(tableRef.getPrivilege());
+        registerPrivReq(builder -> {
+          builder.onTable(rawPath.get(0), rawPath.get(1)).allOf(tableRef.getPrivilege());
+          if (tableRef.requireGrantOption()) {
+            builder.grantOption();
+          }
+          return builder.build();
+        });
+      }
+
+      registerPrivReq(builder -> {
+        builder.onTable(getDefaultDb(), rawPath.get(0)).allOf(tableRef.getPrivilege());
         if (tableRef.requireGrantOption()) {
           builder.grantOption();
         }
-        registerPrivReq(builder.build());
-      }
-      PrivilegeRequestBuilder builder = new PrivilegeRequestBuilder()
-          .onTable(getDefaultDb(), rawPath.get(0))
-          .allOf(tableRef.getPrivilege());
-      if (tableRef.requireGrantOption()) {
-        builder.grantOption();
-      }
-      registerPrivReq(builder.build());
+        return builder.build();
+      });
       throw e;
     } catch (TableLoadingException e) {
       throw new AnalysisException(String.format(
@@ -968,9 +971,10 @@ public class Analyzer {
       Column column = tupleDesc.getTable().getColumn(
           slotDesc.getPath().getRawPath().get(0));
       if (column != null) {
-        registerPrivReq(new PrivilegeRequestBuilder().
-            allOf(Privilege.SELECT).onColumn(tupleDesc.getTableName().getDb(),
-            tupleDesc.getTableName().getTbl(), column.getName()).build());
+        registerPrivReq(builder -> builder
+            .allOf(Privilege.SELECT)
+            .onColumn(tupleDesc.getTableName().getDb(), tupleDesc.getTableName().getTbl(),
+                column.getName()).build());
       }
     }
   }
@@ -2352,7 +2356,11 @@ public class Analyzer {
     return globalState_.queryCtx.client_request.getQuery_options();
   }
   public boolean isDecimalV2() { return getQueryOptions().isDecimal_v2(); }
-  public AuthorizationConfig getAuthzConfig() { return globalState_.authzConfig; }
+  public AuthorizationFactory getAuthzFactory() { return globalState_.authzFactory; }
+  public AuthorizationConfig getAuthzConfig() {
+    return getAuthzFactory().getAuthorizationConfig();
+  }
+  public boolean isAuthzEnabled() { return getAuthzConfig().isEnabled(); }
   public ListMap<TNetworkAddress> getHostIndex() { return globalState_.hostIndex; }
   public ColumnLineageGraph getColumnLineageGraph() { return globalState_.lineageGraph; }
   public TLineageGraph getThriftSerializedLineageGraph() {
@@ -2425,17 +2433,21 @@ public class Analyzer {
       throws AnalysisException, TableLoadingException {
     Preconditions.checkNotNull(tableName);
     Preconditions.checkNotNull(privilege);
-    tableName = getFqTableName(tableName);
+    TableName fqTableName = getFqTableName(tableName);
     for (Privilege priv : privilege) {
       if (priv == Privilege.ANY || addColumnPrivilege) {
-        registerPrivReq(new PrivilegeRequestBuilder()
-            .allOf(priv).onAnyColumn(tableName.getDb(), tableName.getTbl()).build());
+        registerPrivReq(builder ->
+            builder.allOf(priv)
+                .onAnyColumn(fqTableName.getDb(), fqTableName.getTbl())
+                .build());
       } else {
-        registerPrivReq(new PrivilegeRequestBuilder()
-            .allOf(priv).onTable(tableName.getDb(), tableName.getTbl()).build());
+        registerPrivReq(builder ->
+            builder.allOf(priv)
+                .onTable(fqTableName.getDb(), fqTableName.getTbl())
+                .build());
       }
     }
-    FeTable table = getTable(tableName.getDb(), tableName.getTbl());
+    FeTable table = getTable(fqTableName.getDb(), fqTableName.getTbl());
     Preconditions.checkNotNull(table);
     if (addAccessEvent) {
       // Add an audit event for this access
@@ -2443,7 +2455,7 @@ public class Analyzer {
       if (table instanceof FeView) objectType = TCatalogObjectType.VIEW;
       for (Privilege priv : privilege) {
         globalState_.accessEvents.add(new TAccessEvent(
-            tableName.toString(), objectType, priv.toString()));
+            fqTableName.toString(), objectType, priv.toString()));
       }
     }
     return table;
@@ -2509,15 +2521,14 @@ public class Analyzer {
    */
   public FeDb getDb(String dbName, Privilege privilege, boolean throwIfDoesNotExist,
       boolean requireGrantOption) throws AnalysisException {
-    PrivilegeRequestBuilder pb = new PrivilegeRequestBuilder();
-    if (requireGrantOption) {
-      pb.grantOption();
-    }
-    if (privilege == Privilege.ANY) {
-      registerPrivReq(pb.any().onAnyColumn(dbName).build());
-    } else {
-      registerPrivReq(pb.allOf(privilege).onDb(dbName).build());
-    }
+    registerPrivReq(builder -> {
+      if (requireGrantOption) {
+        builder.grantOption();
+      }
+      return privilege == Privilege.ANY ?
+          builder.any().onAnyColumn(dbName).build() :
+          builder.allOf(privilege).onDb(dbName).build();
+    });
 
     FeDb db = getDb(dbName, throwIfDoesNotExist);
     globalState_.accessEvents.add(new TAccessEvent(
@@ -2547,8 +2558,10 @@ public class Analyzer {
    */
   public boolean dbContainsTable(String dbName, String tableName, Privilege privilege)
       throws AnalysisException {
-    registerPrivReq(new PrivilegeRequestBuilder().allOf(privilege)
-        .onTable(dbName,  tableName).build());
+    registerPrivReq(builder ->
+        builder.allOf(privilege)
+            .onTable(dbName, tableName)
+            .build());
     try {
       FeDb db = getCatalog().getDb(dbName);
       if (db == null) {
@@ -2641,6 +2654,16 @@ public class Analyzer {
   }
 
   /**
+   * Registers a new PrivilegeRequest in the analyzer. The given function is used to
+   * create a PrivilegeRequest.
+   */
+  public void registerPrivReq(
+      Function<PrivilegeRequestBuilder, PrivilegeRequest> function) {
+    registerPrivReq(function.apply(new PrivilegeRequestBuilder(
+        getAuthzFactory().getAuthorizableFactory())));
+  }
+
+  /**
    * This method does not require the grant option permission.
    */
   public void registerAuthAndAuditEvent(FeTable table, Privilege priv) {
@@ -2669,13 +2692,13 @@ public class Analyzer {
     }
     // Add privilege request.
     TableName tableName = table.getTableName();
-    PrivilegeRequestBuilder builder = new PrivilegeRequestBuilder()
-        .onTable(tableName.getDb(), tableName.getTbl())
-        .allOf(priv);
-    if (requireGrantOption) {
-      builder.grantOption();
-    }
-    registerPrivReq(builder.build());
+    registerPrivReq(builder -> {
+      builder.onTable(tableName.getDb(), tableName.getTbl()).allOf(priv);
+      if (requireGrantOption) {
+        builder.grantOption();
+      }
+      return builder.build();
+    });
   }
 
   /**
@@ -2683,7 +2706,6 @@ public class Analyzer {
    * is not enabled.
    */
   public String getServerName() {
-    return getAuthzConfig().isEnabled() ? getAuthzConfig().getServerName().intern() :
-        null;
+    return isAuthzEnabled() ? getAuthzConfig().getServerName().intern() : null;
   }
 }
diff --git a/fe/src/main/java/org/apache/impala/analysis/AuthorizationStmt.java b/fe/src/main/java/org/apache/impala/analysis/AuthorizationStmt.java
index 244ff43..a5aff05 100644
--- a/fe/src/main/java/org/apache/impala/analysis/AuthorizationStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/AuthorizationStmt.java
@@ -17,6 +17,7 @@
 
 package org.apache.impala.analysis;
 
+import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.authorization.AuthorizationProvider;
 import org.apache.impala.authorization.User;
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
@@ -34,12 +35,13 @@ public class AuthorizationStmt extends StatementBase {
 
   @Override
   public void analyze(Analyzer analyzer) throws AnalysisException {
-    if (!analyzer.getAuthzConfig().isEnabled()) {
+    AuthorizationConfig authzConfig = analyzer.getAuthzConfig();
+    if (!authzConfig.isEnabled()) {
       throw new AnalysisException("Authorization is not enabled. To enable " +
           "authorization restart Impala with the --server_name=<name> flag.");
     }
-    if (analyzer.getAuthzConfig().getProvider() == AuthorizationProvider.SENTRY) {
-      if (((SentryAuthorizationConfig) analyzer.getAuthzConfig()).isFileBasedPolicy()) {
+    if (authzConfig.getProvider() == AuthorizationProvider.SENTRY) {
+      if (((SentryAuthorizationConfig) authzConfig).isFileBasedPolicy()) {
         throw new AnalysisException("Cannot execute authorization statement using a " +
             "file based policy. To disable file based policies, restart Impala without " +
             "the -authorization_policy_file flag set.");
diff --git a/fe/src/main/java/org/apache/impala/analysis/CollectionTableRef.java b/fe/src/main/java/org/apache/impala/analysis/CollectionTableRef.java
index 2496c20..9965643 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CollectionTableRef.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CollectionTableRef.java
@@ -18,7 +18,6 @@
 package org.apache.impala.analysis;
 
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.common.AnalysisException;
 import com.google.common.base.Preconditions;
 
@@ -105,10 +104,11 @@ public class CollectionTableRef extends TableRef {
       Preconditions.checkNotNull(resolvedPath_.getRootTable());
       analyzer.registerAuthAndAuditEvent(resolvedPath_.getRootTable(), priv_,
           requireGrantOption_);
-      analyzer.registerPrivReq(new PrivilegeRequestBuilder().
-          allOf(Privilege.SELECT).onColumn(desc_.getTableName().getDb(),
-          desc_.getTableName().getTbl(), desc_.getPath().getRawPath().get(0))
-          .build());
+      analyzer.registerPrivReq(builder ->
+          builder.allOf(Privilege.SELECT)
+              .onColumn(desc_.getTableName().getDb(), desc_.getTableName().getTbl(),
+                  desc_.getPath().getRawPath().get(0))
+              .build());
     }
     isAnalyzed_ = true;
     analyzeTableSample(analyzer);
diff --git a/fe/src/main/java/org/apache/impala/analysis/CopyTestCaseStmt.java b/fe/src/main/java/org/apache/impala/analysis/CopyTestCaseStmt.java
index 996a9db..5023963 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CopyTestCaseStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CopyTestCaseStmt.java
@@ -25,7 +25,6 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsAction;
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.catalog.FeDb;
 import org.apache.impala.catalog.FeTable;
 import org.apache.impala.catalog.FeView;
@@ -119,12 +118,14 @@ public class CopyTestCaseStmt extends StatementBase {
       // referenced objects.
       Pair<Set<FeDb>, Set<FeTable>> referencedObjects = getReferencedCatalogObjects();
       for (FeDb db: referencedObjects.first) {
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder().onDb(db.getName()).allOf
-            (Privilege.VIEW_METADATA).build());
+        analyzer.registerPrivReq(builder ->
+            builder.onDb(db.getName()).allOf(Privilege.VIEW_METADATA).build());
       }
       for (FeTable table: referencedObjects.second) {
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder().onTable(table.getDb()
-            .getName(), table.getName()).allOf(Privilege.VIEW_METADATA).build());
+        analyzer.registerPrivReq(builder ->
+            builder.onTable(table.getDb().getName(), table.getName())
+                .allOf(Privilege.VIEW_METADATA)
+                .build());
       }
     } else {
       hdfsPath_.analyze(analyzer, Privilege.ALL, FsAction.READ, /*registerPrivReq*/ true,
diff --git a/fe/src/main/java/org/apache/impala/analysis/CreateFunctionStmtBase.java b/fe/src/main/java/org/apache/impala/analysis/CreateFunctionStmtBase.java
index 2620c0a..e1fa567 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CreateFunctionStmtBase.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CreateFunctionStmtBase.java
@@ -22,7 +22,6 @@ import java.util.Map;
 
 import org.apache.hadoop.fs.permission.FsAction;
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.catalog.FeDb;
 import org.apache.impala.catalog.Function;
 import org.apache.impala.catalog.Type;
@@ -143,9 +142,10 @@ public abstract class CreateFunctionStmtBase extends StatementBase {
       fn_ = createFunction(fnName_, null, null, false);
     }
 
-    analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-        .onFunction(fn_.dbName(), fn_.signatureString()).allOf(Privilege.CREATE)
-        .build());
+    analyzer.registerPrivReq(builder ->
+        builder.onFunction(fn_.dbName(), fn_.signatureString())
+            .allOf(Privilege.CREATE)
+            .build());
 
     db_ = analyzer.getDb(fn_.dbName(), true);
     Function existingFn = db_.getFunction(fn_, Function.CompareMode.IS_INDISTINGUISHABLE);
diff --git a/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java b/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
index 73f134d..35ff006 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CreateTableAsSelectStmt.java
@@ -142,7 +142,7 @@ public class CreateTableAsSelectStmt extends StatementBase {
     // over the full INSERT statement. To avoid duplicate registrations of table/colRefs,
     // create a new root analyzer and clone the query statement for this initial pass.
     Analyzer dummyRootAnalyzer = new Analyzer(analyzer.getStmtTableCache(),
-        analyzer.getQueryCtx(), analyzer.getAuthzConfig());
+        analyzer.getQueryCtx(), analyzer.getAuthzFactory());
     QueryStmt tmpQueryStmt = insertStmt_.getQueryStmt().clone();
     Analyzer tmpAnalyzer = new Analyzer(dummyRootAnalyzer);
     tmpAnalyzer.setUseHiveColLabels(true);
diff --git a/fe/src/main/java/org/apache/impala/analysis/CreateTableStmt.java b/fe/src/main/java/org/apache/impala/analysis/CreateTableStmt.java
index 06eb125..a344ef5 100644
--- a/fe/src/main/java/org/apache/impala/analysis/CreateTableStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/CreateTableStmt.java
@@ -23,7 +23,7 @@ import java.util.Map;
 
 import org.apache.avro.Schema;
 import org.apache.avro.SchemaParseException;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
+import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.catalog.KuduTable;
 import org.apache.impala.catalog.RowFormat;
 import org.apache.impala.common.AnalysisException;
@@ -244,7 +244,8 @@ public class CreateTableStmt extends StatementBase {
    * Kudu tables.
    */
   private void analyzeKuduTableProperties(Analyzer analyzer) throws AnalysisException {
-    if (analyzer.getAuthzConfig().isEnabled()) {
+    AuthorizationConfig authzConfig = analyzer.getAuthzConfig();
+    if (authzConfig.isEnabled()) {
       // Today there is no comprehensive way of enforcing a Sentry authorization policy
       // against tables stored in Kudu. This is why only users with ALL privileges on
       // SERVER may create external Kudu tables or set the master addresses.
@@ -253,10 +254,9 @@ public class CreateTableStmt extends StatementBase {
           MetaStoreUtil.findTblPropKeyCaseInsensitive(
               getTblProperties(), "EXTERNAL") != null;
       if (getTblProperties().containsKey(KuduTable.KEY_MASTER_HOSTS) || isExternal) {
-        String authzServer = analyzer.getAuthzConfig().getServerName();
+        String authzServer = authzConfig.getServerName();
         Preconditions.checkNotNull(authzServer);
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder().onServer(
-            authzServer).all().build());
+        analyzer.registerPrivReq(builder -> builder.onServer(authzServer).all().build());
       }
     }
 
diff --git a/fe/src/main/java/org/apache/impala/analysis/DescribeTableStmt.java b/fe/src/main/java/org/apache/impala/analysis/DescribeTableStmt.java
index 1622656..c03b9be 100644
--- a/fe/src/main/java/org/apache/impala/analysis/DescribeTableStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/DescribeTableStmt.java
@@ -22,7 +22,6 @@ import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.impala.analysis.Path.PathType;
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.catalog.FeTable;
 import org.apache.impala.catalog.StructType;
 import org.apache.impala.catalog.TableLoadingException;
@@ -99,11 +98,15 @@ public class DescribeTableStmt extends StatementBase {
       // an analysis error. We should not accidentally reveal the non-existence of a
       // table/database if the user is not authorized.
       if (rawPath_.size() > 1) {
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-            .onTable(rawPath_.get(0), rawPath_.get(1)).any().build());
+        analyzer.registerPrivReq(builder ->
+            builder.onTable(rawPath_.get(0), rawPath_.get(1))
+                .any()
+                .build());
       }
-      analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-          .onTable(analyzer.getDefaultDb(), rawPath_.get(0)).any().build());
+      analyzer.registerPrivReq(builder ->
+          builder.onTable(analyzer.getDefaultDb(), rawPath_.get(0))
+              .any()
+              .build());
       throw ae;
     } catch (TableLoadingException tle) {
       throw new AnalysisException(tle.getMessage(), tle);
@@ -118,9 +121,12 @@ public class DescribeTableStmt extends StatementBase {
     // Describing a table.
     if (path_.destTable() != null) return;
 
-    analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-        .onColumn(path_.getRootTable().getDb().getName(), path_.getRootTable().getName(),
-        path_.getRawPath().get(0)).any().build());
+    analyzer.registerPrivReq(builder ->
+        builder.onColumn(path_.getRootTable().getDb().getName(),
+            path_.getRootTable().getName(),
+            path_.getRawPath().get(0))
+            .any()
+            .build());
 
     if (path_.destType().isComplexType()) {
       if (outputStyle_ == TDescribeOutputStyle.FORMATTED ||
diff --git a/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java b/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
index ce3a614..b05c286 100644
--- a/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
@@ -20,7 +20,6 @@ package org.apache.impala.analysis;
 import java.util.ArrayList;
 
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.catalog.FeDb;
 import org.apache.impala.catalog.Function;
 import org.apache.impala.catalog.Type;
@@ -84,9 +83,10 @@ public class DropFunctionStmt extends StatementBase {
           false);
     }
 
-    analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-        .onFunction(desc_.dbName(), desc_.signatureString()).allOf(Privilege.DROP)
-        .build());
+    analyzer.registerPrivReq(builder ->
+        builder.onFunction(desc_.dbName(), desc_.signatureString())
+            .allOf(Privilege.DROP)
+            .build());
 
     FeDb db =  analyzer.getDb(desc_.dbName(), false);
     if (db == null && !ifExists_) {
diff --git a/fe/src/main/java/org/apache/impala/analysis/HdfsUri.java b/fe/src/main/java/org/apache/impala/analysis/HdfsUri.java
index 89a3a96..4404009 100644
--- a/fe/src/main/java/org/apache/impala/analysis/HdfsUri.java
+++ b/fe/src/main/java/org/apache/impala/analysis/HdfsUri.java
@@ -24,7 +24,6 @@ import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.permission.FsAction;
 
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.common.AnalysisException;
 import org.apache.impala.common.FileSystemUtil;
 import org.apache.impala.util.FsPermissionChecker;
@@ -120,8 +119,10 @@ public class HdfsUri {
     }
 
     if (registerPrivReq) {
-      analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-          .onUri(uriPath_.toString()).allOf(privilege).build());
+      analyzer.registerPrivReq(builder ->
+          builder.onUri(uriPath_.toString())
+              .allOf(privilege)
+              .build());
     }
   }
 
diff --git a/fe/src/main/java/org/apache/impala/analysis/InsertStmt.java b/fe/src/main/java/org/apache/impala/analysis/InsertStmt.java
index 61d4e64..f3bf94c 100644
--- a/fe/src/main/java/org/apache/impala/analysis/InsertStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/InsertStmt.java
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.catalog.Column;
 import org.apache.impala.catalog.FeFsTable;
 import org.apache.impala.catalog.FeHBaseTable;
@@ -420,9 +419,10 @@ public class InsertStmt extends StatementBase {
       table_ = analyzer.getTable(targetTableName_, privilegeRequired);
     } else {
       targetTableName_ = new TableName(table_.getDb().getName(), table_.getName());
-      PrivilegeRequestBuilder pb = new PrivilegeRequestBuilder();
-      analyzer.registerPrivReq(pb.onTable(table_.getDb().getName(), table_.getName())
-          .allOf(privilegeRequired).build());
+      analyzer.registerPrivReq(builder ->
+          builder.onTable(table_.getDb().getName(), table_.getName())
+              .allOf(privilegeRequired)
+              .build());
     }
 
     // We do not support (in|up)serting into views.
diff --git a/fe/src/main/java/org/apache/impala/analysis/ResetMetadataStmt.java b/fe/src/main/java/org/apache/impala/analysis/ResetMetadataStmt.java
index b5aacec..2ca4cf5 100644
--- a/fe/src/main/java/org/apache/impala/analysis/ResetMetadataStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/ResetMetadataStmt.java
@@ -21,7 +21,6 @@ import java.util.List;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.impala.authorization.Privilege;
-import org.apache.impala.authorization.PrivilegeRequestBuilder;
 import org.apache.impala.common.AnalysisException;
 import org.apache.impala.service.BackendConfig;
 import org.apache.impala.thrift.TResetMetadataRequest;
@@ -149,26 +148,33 @@ public class ResetMetadataStmt extends StatementBase {
           }
         } else {
           // Verify the user has privileges to access this table.
-          analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-              .onTable(dbName, tableName_.getTbl()).allOf(Privilege.REFRESH)
-              .build());
+          analyzer.registerPrivReq(builder ->
+              builder.onTable(dbName, tableName_.getTbl())
+                  .allOf(Privilege.REFRESH)
+                  .build());
         }
         break;
       case REFRESH_AUTHORIZATION:
-        if (!analyzer.getAuthzConfig().isEnabled()) {
+        if (!analyzer.isAuthzEnabled()) {
           throw new AnalysisException("Authorization is not enabled. To enable " +
               "authorization restart Impala with the --server_name=<name> flag.");
         }
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-            .onServer(analyzer.getServerName()).allOf(Privilege.REFRESH).build());
+        analyzer.registerPrivReq(builder ->
+            builder.onServer(analyzer.getServerName())
+                .allOf(Privilege.REFRESH)
+                .build());
         break;
       case REFRESH_FUNCTIONS:
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-            .onDb(database_).allOf(Privilege.REFRESH).build());
+        analyzer.registerPrivReq(builder ->
+            builder.onDb(database_)
+                .allOf(Privilege.REFRESH)
+                .build());
         break;
       case INVALIDATE_METADATA_ALL:
-        analyzer.registerPrivReq(new PrivilegeRequestBuilder()
-            .onServer(analyzer.getServerName()).allOf(Privilege.REFRESH).build());
+        analyzer.registerPrivReq(builder ->
+            builder.onServer(analyzer.getServerName())
+                .allOf(Privilege.REFRESH)
+                .build());
         if (BackendConfig.INSTANCE.getBackendCfg().use_local_catalog) {
           throw new AnalysisException("Global INVALIDATE METADATA is not supported " +
               "when --use_local_catalog is configured.");
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizableColumn.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableColumn.java
new file mode 100644
index 0000000..2f7abd2
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableColumn.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+/**
+ * A class to authorize access to a column.
+ */
+public class AuthorizableColumn extends Authorizable {
+  private final String dbName_;
+  private final String tableName_;
+  private final String columnName_;
+
+  public AuthorizableColumn(String dbName, String tableName, String columnName) {
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(dbName));
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(tableName));
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(columnName));
+    dbName_ = dbName;
+    tableName_ = tableName;
+    columnName_ = columnName;
+  }
+
+  @Override
+  public String getName() { return dbName_ + "." + tableName_ + "." + columnName_; }
+
+  @Override
+  public Type getType() { return Type.COLUMN; }
+
+  @Override
+  public String getFullTableName() { return dbName_ + "." + tableName_; }
+
+  @Override
+  public String getDbName() { return dbName_; }
+
+  @Override
+  public String getTableName() { return tableName_; }
+
+  @Override
+  public String getColumnName() { return columnName_; }
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableDb.java
similarity index 61%
copy from fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
copy to fe/src/main/java/org/apache/impala/authorization/AuthorizableDb.java
index a575262..25de969 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableDb.java
@@ -15,12 +15,28 @@
 // specific language governing permissions and limitations
 // under the License.
 
-
 package org.apache.impala.authorization;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
 /**
- * This enum contains the list of authorization providers supported in Impala.
+ * A class to authorize access to a database.
  */
-public enum AuthorizationProvider {
-  SENTRY
+public class AuthorizableDb extends Authorizable {
+  private final String dbName_;
+
+  public AuthorizableDb(String dbName) {
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(dbName));
+    dbName_ = dbName;
+  }
+
+  @Override
+  public String getName() { return dbName_; }
+
+  @Override
+  public String getDbName() { return getName(); }
+
+  @Override
+  public Type getType() { return Authorizable.Type.DB; }
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizableFactory.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableFactory.java
new file mode 100644
index 0000000..906cbb4
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableFactory.java
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization;
+
+/**
+ * An interface to create a factory class for creating instances of
+ * {@link Authorizable}s.
+ */
+public interface AuthorizableFactory {
+  /**
+   * Creates a new instance of server {@link Authorizable} for a given server name.
+   * Server name can be null.
+   */
+  Authorizable newServer(String serverName);
+
+  /**
+   * Creates a new instance of database {@link Authorizable} for a given database name.
+   */
+  Authorizable newDatabase(String dbName);
+
+  /**
+   * Creates a new instance of table {@link Authorizable} for given database and table
+   * names.
+   */
+  Authorizable newTable(String dbName, String tableName);
+
+  /**
+   * Creates a new instance of column {@link Authorizable} for a given database name and
+   * gives access to all tables and columns.
+   */
+  Authorizable newColumn(String dbName);
+
+  /**
+   * Creates a new instance of column {@link Authorizable} for given database and table
+   * names and gives access to all columns.
+   */
+  Authorizable newColumn(String dbName, String tableName);
+
+  /**
+   * Creates a new instance of column {@link Authorizable} for given database, table, and
+   * column names.
+   */
+  Authorizable newColumn(String dbName, String tableName, String columnName);
+
+  /**
+   * Creates a new instance of URI {@link Authorizable} for a given URI.
+   */
+  Authorizable newUri(String uri);
+
+  /**
+   * Creates a new instance of function {@link Authorizable} for given database and
+   * function names.
+   */
+  Authorizable newFunction(String dbName, String fnName);
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableFn.java
similarity index 53%
copy from fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
copy to fe/src/main/java/org/apache/impala/authorization/AuthorizableFn.java
index a575262..e0e1a92 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableFn.java
@@ -15,12 +15,34 @@
 // specific language governing permissions and limitations
 // under the License.
 
-
 package org.apache.impala.authorization;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
 /**
- * This enum contains the list of authorization providers supported in Impala.
+ * A class to authorize access to a function.
  */
-public enum AuthorizationProvider {
-  SENTRY
+public class AuthorizableFn extends Authorizable {
+  private final String dbName_;
+  private final String fnName_;
+
+  public AuthorizableFn(String dbName, String fnName) {
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(dbName));
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(fnName));
+    dbName_ = dbName;
+    fnName_ = fnName;
+  }
+
+  @Override
+  public String getName() { return dbName_ + "." + fnName_; }
+
+  @Override
+  public Type getType() { return Type.FUNCTION; }
+
+  @Override
+  public String getDbName() { return dbName_; }
+
+  @Override
+  public String getFnName() { return fnName_; }
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableServer.java
similarity index 69%
copy from fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
copy to fe/src/main/java/org/apache/impala/authorization/AuthorizableServer.java
index a575262..0a603a6 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableServer.java
@@ -15,12 +15,21 @@
 // specific language governing permissions and limitations
 // under the License.
 
-
 package org.apache.impala.authorization;
 
 /**
- * This enum contains the list of authorization providers supported in Impala.
+ * A class to authorize access to a server.
  */
-public enum AuthorizationProvider {
-  SENTRY
+public class AuthorizableServer extends Authorizable {
+  private final String serverName_;
+
+  public AuthorizableServer(String serverName) {
+    serverName_ = serverName == null ? "server" : serverName;
+  }
+
+  @Override
+  public String getName() { return serverName_; }
+
+  @Override
+  public Type getType() { return Type.SERVER; }
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableTable.java
similarity index 50%
copy from fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
copy to fe/src/main/java/org/apache/impala/authorization/AuthorizableTable.java
index a575262..d837013 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableTable.java
@@ -15,12 +15,37 @@
 // specific language governing permissions and limitations
 // under the License.
 
-
 package org.apache.impala.authorization;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
 /**
- * This enum contains the list of authorization providers supported in Impala.
+ * A class to authorize access to a table.
  */
-public enum AuthorizationProvider {
-  SENTRY
+public class AuthorizableTable extends Authorizable {
+  private final String dbName_;
+  private final String tableName_;
+
+  public AuthorizableTable(String dbName, String tableName) {
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(dbName));
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(tableName));
+    dbName_ = dbName;
+    tableName_ = tableName;
+  }
+
+  @Override
+  public String getName() { return dbName_ + "." + tableName_; }
+
+  @Override
+  public Type getType() { return Type.TABLE; }
+
+  @Override
+  public String getDbName() { return dbName_; }
+
+  @Override
+  public String getTableName() { return tableName_; }
+
+  @Override
+  public String getFullTableName() { return getName(); }
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizableUri.java
similarity index 64%
copy from fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
copy to fe/src/main/java/org/apache/impala/authorization/AuthorizableUri.java
index a575262..60de4dd 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizableUri.java
@@ -15,12 +15,25 @@
 // specific language governing permissions and limitations
 // under the License.
 
-
 package org.apache.impala.authorization;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
 /**
- * This enum contains the list of authorization providers supported in Impala.
+ * A class to authorize access to a URI.
  */
-public enum AuthorizationProvider {
-  SENTRY
+public class AuthorizableUri extends Authorizable {
+  private final String uriName_;
+
+  public AuthorizableUri(String uriName) {
+    Preconditions.checkArgument(!Strings.isNullOrEmpty(uriName));
+    uriName_ = uriName;
+  }
+
+  @Override
+  public String getName() { return uriName_; }
+
+  @Override
+  public Type getType() { return Type.URI; }
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
index 993d844..80ca985 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
@@ -18,7 +18,6 @@
 package org.apache.impala.authorization;
 
 import java.util.EnumSet;
-import java.util.Set;
 
 import org.apache.impala.authorization.Authorizable.Type;
 import org.apache.impala.common.InternalException;
@@ -34,16 +33,11 @@ public abstract class AuthorizationChecker {
   /*
    * Creates a new AuthorizationChecker based on the config values.
    */
-  public AuthorizationChecker(AuthorizationConfig config) {
+  protected AuthorizationChecker(AuthorizationConfig config) {
     Preconditions.checkNotNull(config);
     config_ = config;
   }
 
-  /*
-   * Returns the configuration used to create this AuthorizationProvider.
-   */
-  public AuthorizationConfig getConfig() { return config_; }
-
   /**
    * Authorizes the PrivilegeRequest, throwing an Authorization exception if
    * the user does not have sufficient privileges.
@@ -93,15 +87,27 @@ public abstract class AuthorizationChecker {
     return hasGrantOption ? " with 'GRANT OPTION'" : "";
   }
 
-  /**
-   * Returns the set of groups this user belongs to.
-   */
-  public abstract Set<String> getUserGroups(User user) throws InternalException;
-
   /*
    * Returns true if the given user has permission to execute the given
-   * request, false otherwise. Always returns true if authorization is disabled.
+   * request, false otherwise. Always returns true if authorization is disabled or the
+   * given user is an admin user.
+   */
+  public boolean hasAccess(User user, PrivilegeRequest request)
+      throws InternalException {
+    Preconditions.checkNotNull(user);
+    Preconditions.checkNotNull(request);
+
+    // If authorization is not enabled the user will always have access. If this is
+    // an internal request, the user will always have permission.
+    if (!config_.isEnabled() || user instanceof ImpalaInternalAdminUser) {
+      return true;
+    }
+    return authorize(user, request);
+  }
+
+  /**
+   * Performs an authorization for a given user.
    */
-  public abstract boolean hasAccess(User user, PrivilegeRequest request)
+  protected abstract boolean authorize(User user, PrivilegeRequest request)
       throws InternalException;
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationFactory.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizationFactory.java
new file mode 100644
index 0000000..d89a2a6
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizationFactory.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization;
+
+import org.apache.impala.service.BackendConfig;
+
+/**
+ * An interface for building an authorization provider. The implementation of
+ * this interface needs to have a constructor that takes {@link BackendConfig}.
+ */
+public interface AuthorizationFactory {
+  AuthorizableFactory DEFAULT_AUTHORIZABLE_FACTORY = new DefaultAuthorizableFactory();
+
+  /**
+   * Creates a new {@link AuthorizationFactory}.
+   */
+  AuthorizationConfig newAuthorizationConfig(BackendConfig backendConfig);
+
+  /**
+   * Gets an instance of {@link AuthorizationConfig}.
+   */
+  AuthorizationConfig getAuthorizationConfig();
+
+  /**
+   * Creates a new instance of {@link AuthorizationChecker}.
+   */
+  AuthorizationChecker newAuthorizationChecker(AuthorizationPolicy authzPolicy);
+
+  /**
+   * Creates a new instance of {@link AuthorizationChecker}.
+   */
+  default AuthorizationChecker newAuthorizationChecker() {
+    return newAuthorizationChecker(null);
+  }
+
+  /**
+   * Gets an instance of {@link AuthorizableFactory}.
+   */
+  default AuthorizableFactory getAuthorizableFactory() {
+    return DEFAULT_AUTHORIZABLE_FACTORY;
+  }
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationPolicy.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizationPolicy.java
index e33f465..4423dd1 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationPolicy.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizationPolicy.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.net.ntp.TimeStamp;
+import org.apache.impala.authorization.sentry.SentryAuthorizationChecker;
 import org.apache.impala.catalog.CatalogException;
 import org.apache.impala.catalog.CatalogObjectCache;
 import org.apache.impala.catalog.CatalogObjectVersionSet;
@@ -494,8 +495,9 @@ public class AuthorizationPolicy {
     result.setRows(new ArrayList<>());
 
     // A user should be considered to not exist if they do not have any groups.
-    Set<String> groupNames = fe.getAuthzChecker().getUserGroups(
-        new org.apache.impala.authorization.User(principalName));
+    Preconditions.checkState(fe.getAuthzChecker() instanceof SentryAuthorizationChecker);
+    Set<String> groupNames = ((SentryAuthorizationChecker) fe.getAuthzChecker())
+        .getUserGroups(new org.apache.impala.authorization.User(principalName));
     if (groupNames.isEmpty()) {
       throw new AnalysisException(String.format("User '%s' does not exist.",
           principalName));
diff --git a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java b/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
index a575262..d155e90 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizationProvider.java
@@ -22,5 +22,6 @@ package org.apache.impala.authorization;
  * This enum contains the list of authorization providers supported in Impala.
  */
 public enum AuthorizationProvider {
-  SENTRY
+  SENTRY,
+  NONE
 }
diff --git a/fe/src/main/java/org/apache/impala/authorization/DefaultAuthorizableFactory.java b/fe/src/main/java/org/apache/impala/authorization/DefaultAuthorizableFactory.java
new file mode 100644
index 0000000..9d4233f
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/DefaultAuthorizableFactory.java
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * A default implementation of {@link AuthorizableFactory}.
+ */
+public class DefaultAuthorizableFactory implements AuthorizableFactory {
+  private static final String ALL = "*";
+
+  @Override
+  public Authorizable newServer(String serverName) {
+    return new AuthorizableServer(serverName);
+  }
+
+  @Override
+  public Authorizable newDatabase(String dbName) {
+    Preconditions.checkNotNull(dbName);
+    return new AuthorizableDb(dbName);
+  }
+
+  @Override
+  public Authorizable newTable(String dbName, String tableName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    return new AuthorizableTable(dbName, tableName);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName) {
+    Preconditions.checkNotNull(dbName);
+    return new AuthorizableColumn(dbName, ALL, ALL);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName, String tableName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    return new AuthorizableColumn(dbName, tableName, ALL);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName, String tableName, String columnName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    Preconditions.checkNotNull(columnName);
+    return new AuthorizableColumn(dbName, tableName, columnName);
+  }
+
+  @Override
+  public Authorizable newUri(String uri) {
+    Preconditions.checkNotNull(uri);
+    return new AuthorizableUri(uri);
+  }
+
+  @Override
+  public Authorizable newFunction(String dbName, String fnName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(fnName);
+    return new AuthorizableFn(dbName, fnName);
+  }
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/NoneAuthorizationFactory.java b/fe/src/main/java/org/apache/impala/authorization/NoneAuthorizationFactory.java
new file mode 100644
index 0000000..0ff1905
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/NoneAuthorizationFactory.java
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import org.apache.impala.common.InternalException;
+import org.apache.impala.service.BackendConfig;
+
+/**
+ * An implementation of {@link AuthorizationFactory} that does not do any
+ * authorization. This is the default implementation when authorization is disabled.
+ */
+public class NoneAuthorizationFactory implements AuthorizationFactory {
+  private final AuthorizationConfig authzConfig_;
+
+  public NoneAuthorizationFactory(BackendConfig backendConfig) {
+    Preconditions.checkNotNull(backendConfig);
+    authzConfig_ = newAuthorizationConfig(backendConfig);
+  }
+
+  /**
+   * This is for testing.
+   */
+  @VisibleForTesting
+  public NoneAuthorizationFactory() {
+    authzConfig_ = disabledAuthorizationConfig();
+  }
+
+  private static AuthorizationConfig disabledAuthorizationConfig() {
+    return new AuthorizationConfig() {
+      @Override
+      public boolean isEnabled() { return false; }
+      @Override
+      public AuthorizationProvider getProvider() { return AuthorizationProvider.NONE; }
+      @Override
+      public String getServerName() { return null; }
+    };
+  }
+
+  @Override
+  public AuthorizationConfig newAuthorizationConfig(BackendConfig backendConfig) {
+    return disabledAuthorizationConfig();
+  }
+
+  @Override
+  public AuthorizationConfig getAuthorizationConfig() { return authzConfig_; }
+
+  @Override
+  public AuthorizationChecker newAuthorizationChecker(AuthorizationPolicy authzPolicy) {
+    return new AuthorizationChecker(authzConfig_) {
+      @Override
+      protected boolean authorize(User user, PrivilegeRequest request)
+          throws InternalException {
+        return true;
+      }
+    };
+  }
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/PrivilegeRequestBuilder.java b/fe/src/main/java/org/apache/impala/authorization/PrivilegeRequestBuilder.java
index 1723219..4cc39cd 100644
--- a/fe/src/main/java/org/apache/impala/authorization/PrivilegeRequestBuilder.java
+++ b/fe/src/main/java/org/apache/impala/authorization/PrivilegeRequestBuilder.java
@@ -18,37 +18,32 @@
 package org.apache.impala.authorization;
 
 import com.google.common.base.Preconditions;
-import org.apache.impala.authorization.sentry.SentryAuthorizableColumn;
-import org.apache.impala.authorization.sentry.SentryAuthorizableDb;
-import org.apache.impala.authorization.sentry.SentryAuthorizableFn;
-import org.apache.impala.authorization.sentry.SentryAuthorizableServer;
-import org.apache.impala.authorization.sentry.SentryAuthorizableTable;
-import org.apache.impala.authorization.sentry.SentryAuthorizableUri;
 
 /**
  * Class that helps build PrivilegeRequest objects.
+ *
  * For example:
- * PrivilegeRequestBuilder builder = new PrivilegeRequestBuilder();
+ * PrivilegeRequestBuilder builder = new PrivilegeRequestBuilder(
+ *     new AuthorizableFactory(AuthorizationProvider.SENTRY));
  * PrivilegeRequest = builder.allOf(Privilege.SELECT).onTable("db", "tbl").build();
- *
- * TODO: In the future, this class could be extended to provide the option to specify
- * multiple permissions. For example:
- * builder.allOf(SELECT, INSERT).onTable(..);
- * It could also be extended to support an "anyOf" to check if the user has any of the
- * permissions specified:
- * builder.anyOf(SELECT, INSERT).onTable(...);
  */
 public class PrivilegeRequestBuilder {
+  private final AuthorizableFactory authzFactory_;
   private Authorizable authorizable_;
   private Privilege privilege_;
   private boolean grantOption_ = false;
 
+  public PrivilegeRequestBuilder(AuthorizableFactory authzFactory) {
+    Preconditions.checkNotNull(authzFactory);
+    authzFactory_ = authzFactory;
+  }
+
   /**
-   * Sets the authorizable object to be a URI.
+   * Sets the authorizable object to be a function.
    */
   public PrivilegeRequestBuilder onFunction(String dbName, String fnName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableFn(dbName, fnName);
+    authorizable_ = authzFactory_.newFunction(dbName, fnName);
     return this;
   }
 
@@ -57,7 +52,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onUri(String uriName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableUri(uriName);
+    authorizable_ = authzFactory_.newUri(uriName);
     return this;
   }
 
@@ -67,7 +62,7 @@ public class PrivilegeRequestBuilder {
   public PrivilegeRequestBuilder onColumn(String dbName, String tableName,
       String columnName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableColumn(dbName, tableName, columnName);
+    authorizable_ = authzFactory_.newColumn(dbName, tableName, columnName);
     return this;
   }
 
@@ -76,7 +71,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onTable(String dbName, String tableName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableTable(dbName, tableName);
+    authorizable_ = authzFactory_.newTable(dbName, tableName);
     return this;
   }
 
@@ -85,7 +80,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onServer(String serverName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableServer(serverName);
+    authorizable_ = authzFactory_.newServer(serverName);
     return this;
   }
 
@@ -94,16 +89,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onDb(String dbName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableDb(dbName);
-    return this;
-  }
-
-  /**
-   * Specifies that permissions on any table in the given database.
-   */
-  public PrivilegeRequestBuilder onAnyTable(String dbName) {
-    Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableTable(dbName);
+    authorizable_ = authzFactory_.newDatabase(dbName);
     return this;
   }
 
@@ -112,7 +98,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onAnyColumn(String dbName, String tableName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableColumn(dbName, tableName);
+    authorizable_ = authzFactory_.newColumn(dbName, tableName);
     return this;
   }
 
@@ -121,7 +107,7 @@ public class PrivilegeRequestBuilder {
    */
   public PrivilegeRequestBuilder onAnyColumn(String dbName) {
     Preconditions.checkState(authorizable_ == null);
-    authorizable_ = new SentryAuthorizableColumn(dbName);
+    authorizable_ = authzFactory_.newColumn(dbName);
     return this;
   }
 
diff --git a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizableFactory.java b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizableFactory.java
new file mode 100644
index 0000000..032236c
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizableFactory.java
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization.sentry;
+
+import com.google.common.base.Preconditions;
+import org.apache.impala.authorization.Authorizable;
+import org.apache.impala.authorization.AuthorizableFactory;
+
+/**
+ * A Sentry implementation of {@link AuthorizableFactory}.
+ */
+public class SentryAuthorizableFactory implements AuthorizableFactory {
+  @Override
+  public Authorizable newServer(String serverName) {
+    return new SentryAuthorizableServer(serverName);
+  }
+
+  @Override
+  public Authorizable newDatabase(String dbName) {
+    Preconditions.checkNotNull(dbName);
+    return new SentryAuthorizableDb(dbName);
+  }
+
+  @Override
+  public Authorizable newTable(String dbName, String tableName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    return new SentryAuthorizableTable(dbName, tableName);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName) {
+    Preconditions.checkNotNull(dbName);
+    return new SentryAuthorizableColumn(dbName);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName, String tableName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    return new SentryAuthorizableColumn(dbName, tableName);
+  }
+
+  @Override
+  public Authorizable newColumn(String dbName, String tableName, String columnName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(tableName);
+    Preconditions.checkNotNull(columnName);
+    return new SentryAuthorizableColumn(dbName, tableName, columnName);
+  }
+
+  @Override
+  public Authorizable newUri(String uri) {
+    Preconditions.checkNotNull(uri);
+    return new SentryAuthorizableUri(uri);
+  }
+
+  @Override
+  public Authorizable newFunction(String dbName, String fnName) {
+    Preconditions.checkNotNull(dbName);
+    Preconditions.checkNotNull(fnName);
+    return new SentryAuthorizableFn(dbName, fnName);
+  }
+}
diff --git a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationChecker.java b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationChecker.java
index c2f6f85..171cbaa 100644
--- a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationChecker.java
+++ b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationChecker.java
@@ -57,7 +57,9 @@ public class SentryAuthorizationChecker extends AuthorizationChecker {
     }
   }
 
-  @Override
+  /**
+   * Returns the set of groups this user belongs to.
+   */
   public Set<String> getUserGroups(User user) throws InternalException {
     try {
       return provider_.getGroupMapping().getGroups(user.getShortName());
@@ -80,16 +82,7 @@ public class SentryAuthorizationChecker extends AuthorizationChecker {
   }
 
   @Override
-  public boolean hasAccess(User user, PrivilegeRequest request) throws InternalException {
-    Preconditions.checkNotNull(user);
-    Preconditions.checkNotNull(request);
-
-    // If authorization is not enabled the user will always have access. If this is
-    // an internal request, the user will always have permission.
-    if (!config_.isEnabled() || user instanceof ImpalaInternalAdminUser) {
-      return true;
-    }
-
+  public boolean authorize(User user, PrivilegeRequest request) throws InternalException {
     EnumSet<ImpalaAction> actions = ImpalaAction.from(request.getPrivilege());
 
     List<DBModelAuthorizable> authorizables = Lists.newArrayList(
diff --git a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationConfig.java b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationConfig.java
index d1aa40a..f47a241 100644
--- a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationConfig.java
+++ b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationConfig.java
@@ -62,13 +62,6 @@ public class SentryAuthorizationConfig implements AuthorizationConfig {
   }
 
   /**
-   * Returns an AuthorizationConfig object that has authorization disabled.
-   */
-  public static SentryAuthorizationConfig createAuthDisabledConfig() {
-    return new SentryAuthorizationConfig(null, null, null, null);
-  }
-
-  /**
    * Returns an AuthorizationConfig object configured to use Hadoop user->group mappings
    * for the authorization provider.
    */
diff --git a/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationFactory.java b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationFactory.java
new file mode 100644
index 0000000..51daee6
--- /dev/null
+++ b/fe/src/main/java/org/apache/impala/authorization/sentry/SentryAuthorizationFactory.java
@@ -0,0 +1,87 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.impala.authorization.sentry;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import org.apache.impala.authorization.AuthorizableFactory;
+import org.apache.impala.authorization.AuthorizationChecker;
+import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationPolicy;
+import org.apache.impala.authorization.AuthorizationFactory;
+import org.apache.impala.service.BackendConfig;
+
+/**
+ * An implementation of  {@link AuthorizationFactory} that uses Sentry.
+ */
+public class SentryAuthorizationFactory implements AuthorizationFactory {
+  private static final SentryAuthorizableFactory AUTHORIZABLE_FACTORY =
+      new SentryAuthorizableFactory();
+
+  private final AuthorizationConfig authzConfig_;
+
+  public SentryAuthorizationFactory(BackendConfig backendConfig) {
+    Preconditions.checkNotNull(backendConfig);
+    authzConfig_ = newAuthorizationConfig(backendConfig);
+  }
+
+  /**
+   * This is for testing.
+   */
+  @VisibleForTesting
+  public SentryAuthorizationFactory(AuthorizationConfig authzConfig) {
+    Preconditions.checkNotNull(authzConfig);
+    authzConfig_ = authzConfig;
+  }
+
+  @Override
+  public AuthorizationConfig newAuthorizationConfig(BackendConfig backendConfig) {
+    String serverName = backendConfig.getBackendCfg().getServer_name();
+    String policyFile = backendConfig.getBackendCfg().getAuthorization_policy_file();
+    String sentryConfigFile = backendConfig.getBackendCfg().getSentry_config();
+    String policyProviderClassName = backendConfig.getBackendCfg()
+        .getAuthorization_policy_provider_class();
+    // The logic for creating Sentry authorization config is inconsistent between
+    // catalogd and impalad. In catalogd, only --sentry_config flag is required to enable
+    // authorization. In impalad, --server_name and --sentry_config are required.
+    // Keeping the same logic for backward compatibility.
+    if (Strings.isNullOrEmpty(serverName)) {
+      // Check if the Sentry Service is configured. If so, create a configuration object.
+      SentryConfig sentryConfig = new SentryConfig(null);
+      if (!Strings.isNullOrEmpty(sentryConfigFile)) {
+        sentryConfig = new SentryConfig(sentryConfigFile);
+        sentryConfig.loadConfig();
+      }
+      return new SentryAuthorizationConfig(sentryConfig);
+    }
+    return new SentryAuthorizationConfig(serverName, policyFile, sentryConfigFile,
+        policyProviderClassName);
+  }
+
+  @Override
+  public AuthorizationConfig getAuthorizationConfig() { return authzConfig_; }
+
+  @Override
+  public AuthorizationChecker newAuthorizationChecker(AuthorizationPolicy authzPolicy) {
+    return new SentryAuthorizationChecker(authzConfig_, authzPolicy);
+  }
+
+  @Override
+  public AuthorizableFactory getAuthorizableFactory() { return AUTHORIZABLE_FACTORY; }
+}
diff --git a/fe/src/main/java/org/apache/impala/service/BackendConfig.java b/fe/src/main/java/org/apache/impala/service/BackendConfig.java
index 6d92364..b6a3ab6 100644
--- a/fe/src/main/java/org/apache/impala/service/BackendConfig.java
+++ b/fe/src/main/java/org/apache/impala/service/BackendConfig.java
@@ -134,6 +134,10 @@ public class BackendConfig {
     return backendCfg_.enable_orc_scanner;
   }
 
+  public String getAuthorizationFactoryClass() {
+    return backendCfg_.getAuthorization_factory_class();
+  }
+
   // Inits the auth_to_local configuration in the static KerberosName class.
   private static void initAuthToLocal() {
     // If auth_to_local is enabled, we read the configuration hadoop.security.auth_to_local
diff --git a/fe/src/main/java/org/apache/impala/service/Frontend.java b/fe/src/main/java/org/apache/impala/service/Frontend.java
index 5d0ae61..11a4729 100644
--- a/fe/src/main/java/org/apache/impala/service/Frontend.java
+++ b/fe/src/main/java/org/apache/impala/service/Frontend.java
@@ -66,6 +66,7 @@ import org.apache.impala.analysis.TruncateStmt;
 import org.apache.impala.authorization.AuthorizationChecker;
 import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.authorization.AuthorizationProvider;
+import org.apache.impala.authorization.AuthorizationFactory;
 import org.apache.impala.authorization.ImpalaInternalAdminUser;
 import org.apache.impala.authorization.Privilege;
 import org.apache.impala.authorization.PrivilegeRequest;
@@ -224,7 +225,7 @@ public class Frontend {
   }
 
   private final FeCatalogManager catalogManager_;
-  private final AuthorizationConfig authzConfig_;
+  private final AuthorizationFactory authzFactory_;
   /**
    * Authorization checker. Initialized and periodically loaded by a task
    * running on the {@link #policyReader_} thread.
@@ -236,8 +237,8 @@ public class Frontend {
 
   private final ImpaladTableUsageTracker impaladTableUsageTracker_;
 
-  public Frontend(AuthorizationConfig authorizationConfig) {
-    this(authorizationConfig, FeCatalogManager.createFromBackendConfig());
+  public Frontend(AuthorizationFactory authzFactory) {
+    this(authzFactory, FeCatalogManager.createFromBackendConfig());
   }
 
   /**
@@ -245,19 +246,18 @@ public class Frontend {
    * updates and will be used for all requests.
    */
   @VisibleForTesting
-  public Frontend(AuthorizationConfig authorizationConfig,
-      FeCatalog testCatalog) {
-    this(authorizationConfig, FeCatalogManager.createForTests(testCatalog));
+  public Frontend(AuthorizationFactory authzFactory, FeCatalog testCatalog) {
+    this(authzFactory, FeCatalogManager.createForTests(testCatalog));
   }
 
-  private Frontend(AuthorizationConfig authorizationConfig,
-      FeCatalogManager catalogManager) {
-    authzConfig_ = authorizationConfig;
+  private Frontend(AuthorizationFactory authzFactory, FeCatalogManager catalogManager) {
     catalogManager_ = catalogManager;
+    authzFactory_ = authzFactory;
 
-    if (authzConfig_.getProvider() == AuthorizationProvider.SENTRY) {
+    AuthorizationConfig authzConfig = authzFactory.getAuthorizationConfig();
+    if (authzConfig.getProvider() == AuthorizationProvider.SENTRY) {
       SentryAuthorizationConfig sentryAuthzConfig =
-          (SentryAuthorizationConfig) authzConfig_;
+          (SentryAuthorizationConfig) authzConfig;
       // Load the authorization policy once at startup, initializing
       // authzChecker_. This ensures that, if the policy fails to load,
       // we will throw an exception and fail to start.
@@ -274,6 +274,8 @@ public class Frontend {
         policyReader_.scheduleAtFixedRate(policyReaderTask,
             delay, AUTHORIZATION_POLICY_RELOAD_INTERVAL_SECS, TimeUnit.SECONDS);
       }
+    } else {
+      authzChecker_.set(authzFactory.newAuthorizationChecker());
     }
     impaladTableUsageTracker_ = ImpaladTableUsageTracker.createFromConfig(
         BackendConfig.INSTANCE);
@@ -293,7 +295,7 @@ public class Frontend {
     public void run() {
       try {
         LOG.info("Reloading authorization policy file from: " + config_.getPolicyFile());
-        authzChecker_.set(new SentryAuthorizationChecker(config_,
+        authzChecker_.set(authzFactory_.newAuthorizationChecker(
             getCatalog().getAuthPolicy()));
       } catch (Exception e) {
         LOG.error("Error reloading policy file: ", e);
@@ -315,8 +317,8 @@ public class Frontend {
     if (!req.is_delta) {
       // In the case that it was a non-delta update, the catalog might have reloaded
       // itself, and we need to reset the AuthorizationChecker accordingly.
-      authzChecker_.set(new SentryAuthorizationChecker(
-          authzConfig_, getCatalog().getAuthPolicy()));
+      authzChecker_.set(authzFactory_.newAuthorizationChecker(
+          getCatalog().getAuthPolicy()));
     }
     return resp;
   }
@@ -533,8 +535,9 @@ public class Frontend {
       ddl.op_type = TCatalogOpType.SHOW_ROLES;
       ShowRolesStmt showRolesStmt = (ShowRolesStmt) analysis.getStmt();
       ddl.setShow_roles_params(showRolesStmt.toThrift());
-      Set<String> groupNames =
-          getAuthzChecker().getUserGroups(analysis.getAnalyzer().getUser());
+      Preconditions.checkState(getAuthzChecker() instanceof SentryAuthorizationChecker);
+      Set<String> groupNames = ((SentryAuthorizationChecker) getAuthzChecker())
+          .getUserGroups(analysis.getAnalyzer().getUser());
       // Check if the user is part of the group (case-sensitive) this SHOW ROLE
       // statement is targeting. If they are already a member of the group,
       // the admin requirement can be removed.
@@ -550,8 +553,8 @@ public class Frontend {
       ShowGrantPrincipalStmt showGrantPrincipalStmt =
           (ShowGrantPrincipalStmt) analysis.getStmt();
       ddl.setShow_grant_principal_params(showGrantPrincipalStmt.toThrift());
-      Set<String> groupNames =
-          getAuthzChecker().getUserGroups(analysis.getAnalyzer().getUser());
+      Set<String> groupNames = ((SentryAuthorizationChecker) getAuthzChecker())
+          .getUserGroups(analysis.getAnalyzer().getUser());
       // User must be an admin to execute this operation if they have not been granted
       // this principal, or the same user as the request.
       boolean requiresAdmin;
@@ -784,11 +787,12 @@ public class Frontend {
   private List<String> doGetTableNames(String dbName, PatternMatcher matcher,
       User user) throws ImpalaException {
     List<String> tblNames = getCatalog().getTableNames(dbName, matcher);
-    if (authzConfig_.isEnabled()) {
+    if (authzFactory_.getAuthorizationConfig().isEnabled()) {
       Iterator<String> iter = tblNames.iterator();
       while (iter.hasNext()) {
         String tblName = iter.next();
-        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder()
+        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder(
+            authzFactory_.getAuthorizableFactory())
             .any().onAnyColumn(dbName, tblName).build();
         if (!authzChecker_.get().hasAccess(user, privilegeRequest)) {
           iter.remove();
@@ -810,10 +814,11 @@ public class Frontend {
     for (Column column: table.getColumnsInHiveOrder()) {
       String colName = column.getName();
       if (!matcher.matches(colName)) continue;
-      if (authzConfig_.isEnabled()) {
-        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder()
+      if (authzFactory_.getAuthorizationConfig().isEnabled()) {
+        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder(
+            authzFactory_.getAuthorizableFactory())
             .any().onColumn(table.getTableName().getDb(), table.getTableName().getTbl(),
-            colName).build();
+                colName).build();
         if (!authzChecker_.get().hasAccess(user, privilegeRequest)) continue;
       }
       columns.add(column);
@@ -830,7 +835,7 @@ public class Frontend {
     List<? extends FeDb> dbs = getCatalog().getDbs(matcher);
     // If authorization is enabled, filter out the databases the user does not
     // have permissions on.
-    if (authzConfig_.isEnabled()) {
+    if (authzFactory_.getAuthorizationConfig().isEnabled()) {
       Iterator<? extends FeDb> iter = dbs.iterator();
       while (iter.hasNext()) {
         FeDb db = iter.next();
@@ -849,8 +854,8 @@ public class Frontend {
       // Default DB should always be shown.
       return true;
     }
-    PrivilegeRequest request = new PrivilegeRequestBuilder()
-        .any().onAnyColumn(db.getName()).build();
+    PrivilegeRequest request = new PrivilegeRequestBuilder(
+        authzFactory_.getAuthorizableFactory()).any().onAnyColumn(db.getName()).build();
     return authzChecker_.get().hasAccess(user, request);
   }
 
@@ -1018,9 +1023,10 @@ public class Frontend {
     FeTable table = getCatalog().getTable(tableName.db_name,
         tableName.table_name);
     List<Column> filteredColumns;
-    if (authzConfig_.isEnabled()) {
+    if (authzFactory_.getAuthorizationConfig().isEnabled()) {
       // First run a table check
-      PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder()
+      PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder(
+          authzFactory_.getAuthorizableFactory())
           .allOf(Privilege.VIEW_METADATA).onTable(table.getDb().getName(),
               table.getName())
           .build();
@@ -1029,7 +1035,8 @@ public class Frontend {
         filteredColumns = new ArrayList<Column>();
         for (Column col: table.getColumnsInHiveOrder()) {
           String colName = col.getName();
-          privilegeRequest = new PrivilegeRequestBuilder()
+          privilegeRequest = new PrivilegeRequestBuilder(
+              authzFactory_.getAuthorizableFactory())
               .allOf(Privilege.VIEW_METADATA)
               .onColumn(table.getDb().getName(), table.getName(), colName)
               .build();
@@ -1057,14 +1064,15 @@ public class Frontend {
       TDescribeResult result = DescribeResultFactory.buildDescribeFormattedResult(table,
           filteredColumns);
       // Filter out LOCATION text
-      if (authzConfig_.isEnabled()) {
-        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder()
+      if (authzFactory_.getAuthorizationConfig().isEnabled()) {
+        PrivilegeRequest privilegeRequest = new PrivilegeRequestBuilder(
+            authzFactory_.getAuthorizableFactory())
             .allOf(Privilege.VIEW_METADATA)
             .onTable(table.getDb().getName(),table.getName())
             .build();
         // Only filter if the user doesn't have table access.
         if (!authzChecker_.get().hasAccess(user, privilegeRequest)) {
-          List<TResultRow> results = new ArrayList<TResultRow>();
+          List<TResultRow> results = new ArrayList<>();
           for(TResultRow row: result.getResults()) {
             String stringVal = row.getColVals().get(0).getString_val();
             if (!stringVal.contains("Location")) {
@@ -1286,7 +1294,7 @@ public class Frontend {
     StmtTableCache stmtTableCache = metadataLoader.loadTables(stmt);
 
     // Analyze and authorize stmt
-    AnalysisContext analysisCtx = new AnalysisContext(queryCtx, authzConfig_, timeline);
+    AnalysisContext analysisCtx = new AnalysisContext(queryCtx, authzFactory_, timeline);
     AnalysisResult analysisResult =
         analysisCtx.analyzeAndAuthorize(stmt, stmtTableCache, authzChecker_.get());
     LOG.info("Analysis finished.");
diff --git a/fe/src/main/java/org/apache/impala/service/JniCatalog.java b/fe/src/main/java/org/apache/impala/service/JniCatalog.java
index bdcb139..a25f7a2 100644
--- a/fe/src/main/java/org/apache/impala/service/JniCatalog.java
+++ b/fe/src/main/java/org/apache/impala/service/JniCatalog.java
@@ -18,7 +18,6 @@
 package org.apache.impala.service;
 
 import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -26,8 +25,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
-import org.apache.impala.authorization.sentry.SentryConfig;
+import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationFactory;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.authorization.User;
 import org.apache.impala.catalog.CatalogException;
 import org.apache.impala.catalog.CatalogServiceCatalog;
@@ -107,18 +107,33 @@ public class JniCatalog {
     GlogAppender.Install(TLogLevel.values()[cfg.impala_log_lvl],
         TLogLevel.values()[cfg.non_impala_java_vlog]);
 
-    // Check if the Sentry Service is configured. If so, create a configuration object.
-    SentryConfig sentryConfig = new SentryConfig(null);
-    if (!Strings.isNullOrEmpty(cfg.sentry_config)) {
-      sentryConfig = new SentryConfig(cfg.sentry_config);
-      sentryConfig.loadConfig();
+    AuthorizationFactory authzFactory;
+    try {
+      authzFactory = (AuthorizationFactory) Class.forName(
+          BackendConfig.INSTANCE.getAuthorizationFactoryClass())
+          .getConstructor(BackendConfig.class).newInstance(BackendConfig.INSTANCE);
+    } catch (Exception e) {
+      String msg = String.format("Unable to instantiate authorization provider: %s",
+          BackendConfig.INSTANCE.getAuthorizationFactoryClass());
+      LOG.error(msg);
+      throw new InternalException(msg, e);
+    }
+    AuthorizationConfig authzConfig = authzFactory.getAuthorizationConfig();
+    if (!authzConfig.isEnabled()) {
+      // For backward compatibility to keep the existing behavior, when authorization
+      // is not enabled, we need to use a dummy authorization config.
+      authzFactory = new NoneAuthorizationFactory(BackendConfig.INSTANCE);
+      authzConfig = authzFactory.getAuthorizationConfig();
+      LOG.info("Authorization is 'DISABLED'.");
+    } else {
+      LOG.info(String.format("Authorization is 'ENABLED' using %s.",
+          authzConfig.getProvider()));
     }
     LOG.info(JniUtil.getJavaVersion());
 
     catalog_ = new CatalogServiceCatalog(cfg.load_catalog_in_background,
         cfg.num_metadata_loading_threads, cfg.initial_hms_cnxn_timeout_s,
-        new SentryAuthorizationConfig(sentryConfig), getServiceId(), cfg.principal,
-        cfg.local_library_path);
+        authzConfig, getServiceId(), cfg.principal, cfg.local_library_path);
     try {
       catalog_.reset();
     } catch (CatalogException e) {
diff --git a/fe/src/main/java/org/apache/impala/service/JniFrontend.java b/fe/src/main/java/org/apache/impala/service/JniFrontend.java
index 1facbe8..a28db21 100644
--- a/fe/src/main/java/org/apache/impala/service/JniFrontend.java
+++ b/fe/src/main/java/org/apache/impala/service/JniFrontend.java
@@ -44,9 +44,12 @@ import org.apache.hadoop.security.ShellBasedUnixGroupsMapping;
 import org.apache.hadoop.security.ShellBasedUnixGroupsNetgroupMapping;
 import org.apache.impala.analysis.DescriptorTable;
 import org.apache.impala.analysis.ToSqlUtils;
+import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationFactory;
 import org.apache.impala.authorization.ImpalaInternalAdminUser;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.authorization.User;
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.sentry.SentryAuthorizationChecker;
 import org.apache.impala.catalog.FeDataSource;
 import org.apache.impala.catalog.FeDb;
 import org.apache.impala.catalog.Function;
@@ -137,21 +140,28 @@ public class JniFrontend {
     GlogAppender.Install(TLogLevel.values()[cfg.impala_log_lvl],
         TLogLevel.values()[cfg.non_impala_java_vlog]);
 
-    // Validate the authorization configuration before initializing the Frontend.
-    // If there are any configuration problems Impala startup will fail.
-    SentryAuthorizationConfig authConfig = new SentryAuthorizationConfig(cfg.server_name,
-        cfg.authorization_policy_file, cfg.sentry_config,
-        cfg.authorization_policy_provider_class);
-    if (authConfig.isEnabled()) {
-      LOG.info(String.format("Authorization is 'ENABLED' using %s",
-          authConfig.isFileBasedPolicy() ? " file based policy from: " +
-          authConfig.getPolicyFile() : " using Sentry Policy Service."));
-    } else {
+    AuthorizationFactory authzFactory;
+    try {
+      authzFactory = (AuthorizationFactory) Class.forName(
+          BackendConfig.INSTANCE.getAuthorizationFactoryClass())
+          .getConstructor(BackendConfig.class).newInstance(BackendConfig.INSTANCE);
+    } catch (Exception e) {
+      String msg = String.format("Unable to instantiate authorization provider: %s",
+          BackendConfig.INSTANCE.getAuthorizationFactoryClass());
+      throw new InternalException(msg,e);
+    }
+    AuthorizationConfig authzConfig = authzFactory.getAuthorizationConfig();
+    if (!authzConfig.isEnabled()) {
+      // For backward compatibility to keep the existing behavior, when authorization
+      // is not enabled, we need to use a dummy authorization config.
+      authzFactory = new NoneAuthorizationFactory(BackendConfig.INSTANCE);
       LOG.info("Authorization is 'DISABLED'.");
+    } else {
+      LOG.info(String.format("Authorization is 'ENABLED' using %s.",
+          authzConfig.getProvider()));
     }
     LOG.info(JniUtil.getJavaVersion());
-
-    frontend_ = new Frontend(authConfig);
+    frontend_ = new Frontend(authzFactory);
   }
 
   /**
@@ -528,7 +538,10 @@ public class JniFrontend {
       User user = new User(params.getRequesting_user());
       Set<String> groupNames;
       if (params.isIs_show_current_roles()) {
-        groupNames = frontend_.getAuthzChecker().getUserGroups(user);
+        Preconditions.checkState(
+            frontend_.getAuthzChecker() instanceof SentryAuthorizationChecker);
+        groupNames = ((SentryAuthorizationChecker) frontend_.getAuthzChecker())
+            .getUserGroups(user);
       } else {
         Preconditions.checkState(params.isSetGrant_group());
         groupNames = Sets.newHashSet(params.getGrant_group());
diff --git a/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java b/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
index 994b872..6b33591 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
@@ -19,7 +19,9 @@ package org.apache.impala.analysis;
 
 import java.util.HashSet;
 
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.sentry.SentryAuthorizationFactory;
 import org.apache.impala.catalog.Catalog;
 import org.apache.impala.catalog.Role;
 import org.apache.impala.catalog.User;
@@ -67,7 +69,8 @@ public class AnalyzeAuthStmtsTest extends FrontendTestBase {
         defaultDb, System.getProperty("user.name"));
     EventSequence timeline = new EventSequence("Authorization Test");
     AnalysisContext analysisCtx = new AnalysisContext(queryCtx,
-        SentryAuthorizationConfig.createHadoopGroupAuthConfig("server1", null, null),
+        new SentryAuthorizationFactory(
+            SentryAuthorizationConfig.createHadoopGroupAuthConfig("server1", null, null)),
         timeline);
     return analysisCtx;
   }
@@ -77,7 +80,7 @@ public class AnalyzeAuthStmtsTest extends FrontendTestBase {
         Catalog.DEFAULT_DB, System.getProperty("user.name"));
     EventSequence timeline = new EventSequence("Authorization Test");
     AnalysisContext analysisCtx = new AnalysisContext(queryCtx,
-        SentryAuthorizationConfig.createAuthDisabledConfig(), timeline);
+        new NoneAuthorizationFactory(), timeline);
     return analysisCtx;
   }
 
@@ -308,7 +311,8 @@ public class AnalyzeAuthStmtsTest extends FrontendTestBase {
         Catalog.DEFAULT_DB, "");
     EventSequence timeline = new EventSequence("Authorization Test");
     AnalysisContext noUserNameCtx = new AnalysisContext(noUserNameQueryCtx,
-        SentryAuthorizationConfig.createHadoopGroupAuthConfig("server1", null, null),
+        new SentryAuthorizationFactory(
+            SentryAuthorizationConfig.createHadoopGroupAuthConfig("server1", null, null)),
         timeline);
     AnalysisError("GRANT ALL ON SERVER TO myRole", noUserNameCtx,
         "Cannot execute authorization statement with an empty username.");
diff --git a/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java b/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
index a2e8c57..4c2f87a 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuditingTest.java
@@ -21,6 +21,7 @@ import java.util.Set;
 
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
 import org.apache.impala.authorization.AuthorizationException;
+import org.apache.impala.authorization.sentry.SentryAuthorizationFactory;
 import org.apache.impala.catalog.Catalog;
 import org.apache.impala.catalog.ImpaladCatalog;
 import org.apache.impala.common.AnalysisException;
@@ -372,7 +373,7 @@ public class AuditingTest extends FrontendTestBase {
             "/does/not/exist", System.getenv("IMPALA_HOME") +
             "/fe/src/test/resources/sentry-site.xml");
     try (ImpaladCatalog catalog = new ImpaladTestCatalog(config)) {
-      Frontend fe = new Frontend(config, catalog);
+      Frontend fe = new Frontend(new SentryAuthorizationFactory(config), catalog);
       AnalysisContext analysisCtx = createAnalysisCtx(config);
       // We should get an audit event even when an authorization failure occurs.
       try {
diff --git a/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java b/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java
index 19befb7..2a91635 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java
@@ -33,6 +33,7 @@ import org.apache.impala.authorization.PrivilegeRequest;
 import org.apache.impala.authorization.User;
 import org.apache.impala.authorization.AuthorizationException;
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.sentry.SentryAuthorizationFactory;
 import org.apache.impala.authorization.sentry.SentryPolicyService;
 import org.apache.impala.catalog.Role;
 import org.apache.impala.catalog.ScalarFunction;
@@ -78,7 +79,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     SentryAuthorizationConfig authzConfig = createAuthorizationConfig();
     analysisContext_ = createAnalysisCtx(authzConfig, USER.getName());
     authzCatalog_ = new ImpaladTestCatalog(authzConfig);
-    authzFrontend_ = new Frontend(authzConfig, authzCatalog_);
+    authzFrontend_ = new Frontend(new SentryAuthorizationFactory(authzConfig),
+        authzCatalog_);
     sentryService_ = new SentryPolicyService(authzConfig.getSentryConfig());
   }
 
@@ -165,8 +167,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
         expectedAuthorizables);
     verifyPrivilegeReqs(createAnalysisCtx("functional"),
         "select alltypes.id from alltypes", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "select id from alltypes",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "select id from alltypes", expectedAuthorizables);
     verifyPrivilegeReqs("select alltypes.id from functional.alltypes",
         expectedAuthorizables);
     verifyPrivilegeReqs("select a.id from functional.alltypes a", expectedAuthorizables);
@@ -175,8 +177,9 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("insert into functional.alltypes(id) partition(month, year) " +
         "values(1, 1, 2018)", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "insert into alltypes(id) " +
-        "partition(month, year) values(1, 1, 2018)", expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "insert into alltypes(id) partition(month, year) values(1, 1, 2018)",
+        expectedAuthorizables);
 
     // Insert with constant select.
     expectedAuthorizables = Sets.newHashSet("functional.zipcode_incomes");
@@ -209,8 +212,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     // Reset metadata.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("invalidate metadata functional.alltypes", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "invalidate metadata alltypes",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "invalidate metadata alltypes", expectedAuthorizables);
     verifyPrivilegeReqs("refresh functional.alltypes", expectedAuthorizables);
     verifyPrivilegeReqs(createAnalysisCtx("functional"), "refresh alltypes",
         expectedAuthorizables);
@@ -224,8 +227,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     // Show partitions.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("show partitions functional.alltypes", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "show partitions alltypes",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "show partitions alltypes", expectedAuthorizables);
 
     // Show range partitions.
     expectedAuthorizables = Sets.newHashSet("functional_kudu.dimtbl");
@@ -238,14 +241,14 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("show table stats functional.alltypes",
         expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "show table stats alltypes",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "show table stats alltypes", expectedAuthorizables);
 
     // Show column stats.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("show column stats functional.alltypes", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "show column stats alltypes",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "show column stats alltypes", expectedAuthorizables);
 
     // Show create table.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
@@ -276,8 +279,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     expectedAuthorizables = Sets.newHashSet("functional.new_table");
     verifyPrivilegeReqs("create table functional.new_table(i int)",
         expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "create table new_table(i int)",
-        expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "create table new_table(i int)", expectedAuthorizables);
 
     // Create view.
     expectedAuthorizables = Sets.newHashSet("functional.new_view");
@@ -295,7 +298,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
     // Drop view.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes_view");
     verifyPrivilegeReqs("drop view functional.alltypes_view", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "drop view alltypes_view",
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "drop view alltypes_view",
         expectedAuthorizables);
 
     // Update table.
@@ -320,22 +324,23 @@ public class AuthorizationStmtTest extends FrontendTestBase {
         "functional_kudu.alltypes",
         "functional_kudu.alltypes.id");
     verifyPrivilegeReqs("delete from functional_kudu.alltypes", expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"), "delete from alltypes",
+    verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"),
+        "delete from alltypes",
         expectedAuthorizables);
 
     // Alter table.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes");
     verifyPrivilegeReqs("alter table functional.alltypes add columns(c1 int)",
         expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "alter table alltypes " +
-        "add columns(c1 int)", expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "alter table alltypes add columns(c1 int)", expectedAuthorizables);
 
     // Alter view.
     expectedAuthorizables = Sets.newHashSet("functional.alltypes_view");
     verifyPrivilegeReqs("alter view functional.alltypes_view as select 1",
         expectedAuthorizables);
-    verifyPrivilegeReqs(createAnalysisCtx("functional"), "alter view alltypes_view as " +
-        "select 1", expectedAuthorizables);
+    verifyPrivilegeReqs(createAnalysisCtx("functional"),
+        "alter view alltypes_view as select 1", expectedAuthorizables);
   }
 
   @Test
@@ -2704,7 +2709,7 @@ public class AuthorizationStmtTest extends FrontendTestBase {
       for (AuthzTest test: new AuthzTest[] {
           authorize("select functional.to_lower('ABCDEF')"),
           // Also test with expression rewrite enabled.
-          authorize(createAnalysisCtx(options),
+          authorize(createAnalysisCtx(options, createAuthorizationConfig()),
               "select functional.to_lower('ABCDEF')")}) {
         test.ok(onServer(TPrivilegeLevel.SELECT))
             .ok(onDatabase("functional", TPrivilegeLevel.ALL))
@@ -3253,7 +3258,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
 
   private void verifyPrivilegeReqs(String stmt, Set<String> expectedPrivilegeNames)
       throws ImpalaException {
-    verifyPrivilegeReqs(createAnalysisCtx(), stmt, expectedPrivilegeNames);
+    verifyPrivilegeReqs(createAnalysisCtx(createAuthorizationConfig()), stmt,
+        expectedPrivilegeNames);
   }
 
   private void verifyPrivilegeReqs(AnalysisContext ctx, String stmt,
diff --git a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
index 3661fbb..b661ac3 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
@@ -37,6 +37,7 @@ import org.apache.impala.authorization.AuthorizationConfig;
 import org.apache.impala.authorization.User;
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
 import org.apache.impala.authorization.AuthorizationException;
+import org.apache.impala.authorization.sentry.SentryAuthorizationFactory;
 import org.apache.impala.authorization.sentry.SentryPolicyService;
 import org.apache.impala.catalog.FeDb;
 import org.apache.impala.catalog.ImpaladCatalog;
@@ -175,7 +176,7 @@ public class AuthorizationTest extends FrontendTestBase {
   public AuthorizationTest(TestContext ctx) throws Exception {
     ctx_ = ctx;
     analysisContext_ = createAnalysisCtx(ctx_.authzConfig, USER.getName());
-    fe_ = new Frontend(ctx_.authzConfig, ctx_.catalog);
+    fe_ = new Frontend(new SentryAuthorizationFactory(ctx_.authzConfig), ctx_.catalog);
   }
 
   public static SentryAuthorizationConfig createPolicyFileAuthzConfig() {
@@ -857,7 +858,7 @@ public class AuthorizationTest extends FrontendTestBase {
           new Configuration().get(HADOOP_SECURITY_AUTH_TO_LOCAL, "DEFAULT"));
       User user = new User("authtest/hostname@REALM.COM");
       AnalysisContext ctx = createAnalysisCtx(authzConfig, user.getName());
-      Frontend fe = new Frontend(authzConfig, catalog);
+      Frontend fe = new Frontend(new SentryAuthorizationFactory(authzConfig), catalog);
 
       // Can select from table that user has privileges on.
       AuthzOk(fe, ctx, "select * from tpcds.customer");
@@ -992,7 +993,8 @@ public class AuthorizationTest extends FrontendTestBase {
     try {
       config = new SentryAuthorizationConfig("server1", AUTHZ_POLICY_FILE, sentryConfig,
           "ClassDoesNotExist");
-      Assert.assertTrue(config.isEnabled());      fail("Expected configuration to fail.");
+      Assert.assertTrue(config.isEnabled());
+      fail("Expected configuration to fail.");
     } catch (IllegalArgumentException e) {
       Assert.assertEquals(
           "The authorization policy provider class 'ClassDoesNotExist' was not found.",
@@ -1030,12 +1032,13 @@ public class AuthorizationTest extends FrontendTestBase {
     SentryAuthorizationConfig authzConfig = new SentryAuthorizationConfig("server1",
         AUTHZ_POLICY_FILE, ctx_.authzConfig.getSentryConfig().getConfigFile(),
         LocalGroupResourceAuthorizationProvider.class.getName());
+    SentryAuthorizationFactory authzFactory = new SentryAuthorizationFactory(authzConfig);
     try (ImpaladCatalog catalog = new ImpaladTestCatalog(authzConfig)) {
       // Create an analysis context + FE with the test user
       // (as defined in the policy file)
       User user = new User("test_user");
       AnalysisContext ctx = createAnalysisCtx(authzConfig, user.getName());
-      Frontend fe = new Frontend(authzConfig, catalog);
+      Frontend fe = new Frontend(authzFactory, catalog);
 
       // Can select from table that user has privileges on.
       AuthzOk(fe, ctx, "select * from functional.alltypesagg");
@@ -1047,7 +1050,7 @@ public class AuthorizationTest extends FrontendTestBase {
       // Verify with the admin user
       user = new User("admin_user");
       ctx = createAnalysisCtx(authzConfig, user.getName());
-      fe = new Frontend(authzConfig, catalog);
+      fe = new Frontend(authzFactory, catalog);
 
       // Admin user should have privileges to do anything
       AuthzOk(fe, ctx, "select * from functional.alltypesagg");
@@ -1060,7 +1063,8 @@ public class AuthorizationTest extends FrontendTestBase {
 
   private void TestWithIncorrectConfig(AuthorizationConfig authzConfig, User user)
       throws ImpalaException {
-    Frontend fe = new Frontend(authzConfig, ctx_.catalog);
+    Frontend fe = new Frontend(new SentryAuthorizationFactory(authzConfig),
+        ctx_.catalog);
     AnalysisContext ctx = createAnalysisCtx(authzConfig, user.getName());
     AuthzError(fe, ctx, "select * from functional.alltypesagg",
         "User '%s' does not have privileges to execute 'SELECT' on: " +
diff --git a/fe/src/test/java/org/apache/impala/analysis/StmtMetadataLoaderTest.java b/fe/src/test/java/org/apache/impala/analysis/StmtMetadataLoaderTest.java
index 08ab02c..caba736 100644
--- a/fe/src/test/java/org/apache/impala/analysis/StmtMetadataLoaderTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/StmtMetadataLoaderTest.java
@@ -20,7 +20,7 @@ package org.apache.impala.analysis;
 import java.util.Arrays;
 
 import org.apache.impala.analysis.StmtMetadataLoader.StmtTableCache;
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.catalog.Catalog;
 import org.apache.impala.catalog.FeTable;
 import org.apache.impala.common.ImpalaException;
@@ -38,8 +38,7 @@ public class StmtMetadataLoaderTest {
       String[] expectedDbs, String[] expectedTables)
       throws ImpalaException {
     try (ImpaladTestCatalog catalog = new ImpaladTestCatalog()) {
-      Frontend fe = new Frontend(SentryAuthorizationConfig.createAuthDisabledConfig(),
-          catalog);
+      Frontend fe = new Frontend(new NoneAuthorizationFactory(), catalog);
       StatementBase stmt = Parser.parse(stmtStr);
       // Catalog is fresh and no tables are cached.
       validateUncached(stmt, fe, expectedNumLoadRequests, expectedNumCatalogUpdates,
@@ -51,8 +50,7 @@ public class StmtMetadataLoaderTest {
 
   private void testNoLoad(String stmtStr) throws ImpalaException {
     try (ImpaladTestCatalog catalog = new ImpaladTestCatalog()) {
-      Frontend fe = new Frontend(SentryAuthorizationConfig.createAuthDisabledConfig(),
-          catalog);
+      Frontend fe = new Frontend(new NoneAuthorizationFactory(), catalog);
       StatementBase stmt = Parser.parse(stmtStr);
       validateCached(stmt, fe, new String[]{}, new String[]{});
     }
diff --git a/fe/src/test/java/org/apache/impala/common/FrontendFixture.java b/fe/src/test/java/org/apache/impala/common/FrontendFixture.java
index 0c8e648..c685e6b 100644
--- a/fe/src/test/java/org/apache/impala/common/FrontendFixture.java
+++ b/fe/src/test/java/org/apache/impala/common/FrontendFixture.java
@@ -37,7 +37,9 @@ import org.apache.impala.analysis.StatementBase;
 import org.apache.impala.analysis.StmtMetadataLoader;
 import org.apache.impala.analysis.StmtMetadataLoader.StmtTableCache;
 import org.apache.impala.authorization.AuthorizationConfig;
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.AuthorizationProvider;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
+import org.apache.impala.authorization.sentry.SentryAuthorizationFactory;
 import org.apache.impala.catalog.AggregateFunction;
 import org.apache.impala.catalog.Catalog;
 import org.apache.impala.catalog.CatalogException;
@@ -91,8 +93,8 @@ public class FrontendFixture {
   protected final ImpaladTestCatalog catalog_ = new ImpaladTestCatalog();
 
   // The actual Impala frontend that backs this fixture.
-  protected final Frontend frontend_ = new Frontend(
-      SentryAuthorizationConfig.createAuthDisabledConfig(), catalog_);
+  protected final Frontend frontend_ = new Frontend(new NoneAuthorizationFactory(),
+      catalog_);
 
   // Test-local list of test databases and tables.
   protected final List<Db> testDbs_ = new ArrayList<>();
@@ -294,16 +296,24 @@ public class FrontendFixture {
         defaultDb, System.getProperty("user.name"));
     EventSequence timeline = new EventSequence("Frontend Test Timeline");
     AnalysisContext analysisCtx = new AnalysisContext(queryCtx,
-        SentryAuthorizationConfig.createAuthDisabledConfig(), timeline);
+        new NoneAuthorizationFactory(), timeline);
     return analysisCtx;
   }
 
   public AnalysisContext createAnalysisCtx(TQueryOptions queryOptions) {
+    return createAnalysisCtx(queryOptions,
+        new NoneAuthorizationFactory().getAuthorizationConfig());
+  }
+
+  public AnalysisContext createAnalysisCtx(TQueryOptions queryOptions,
+      AuthorizationConfig authzConfig) {
     TQueryCtx queryCtx = TestUtils.createQueryContext();
     queryCtx.client_request.query_options = queryOptions;
     EventSequence timeline = new EventSequence("Frontend Test Timeline");
     AnalysisContext analysisCtx = new AnalysisContext(queryCtx,
-        SentryAuthorizationConfig.createAuthDisabledConfig(), timeline);
+        authzConfig.getProvider() == AuthorizationProvider.SENTRY ?
+            new SentryAuthorizationFactory(authzConfig) : new NoneAuthorizationFactory(),
+        timeline);
     return analysisCtx;
   }
 
@@ -315,7 +325,10 @@ public class FrontendFixture {
       String user) {
     TQueryCtx queryCtx = TestUtils.createQueryContext(Catalog.DEFAULT_DB, user);
     EventSequence timeline = new EventSequence("Frontend Test Timeline");
-    AnalysisContext analysisCtx = new AnalysisContext(queryCtx, authzConfig, timeline);
+    AnalysisContext analysisCtx = new AnalysisContext(queryCtx,
+        authzConfig.getProvider() == AuthorizationProvider.SENTRY ?
+        new SentryAuthorizationFactory(authzConfig) : new NoneAuthorizationFactory(),
+        timeline);
     return analysisCtx;
   }
 
diff --git a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
index d7d49c0..bd789d5 100644
--- a/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
+++ b/fe/src/test/java/org/apache/impala/common/FrontendTestBase.java
@@ -190,6 +190,11 @@ public class FrontendTestBase extends AbstractFrontendTest {
     return feFixture_.createAnalysisCtx(queryOptions);
   }
 
+  protected AnalysisContext createAnalysisCtx(TQueryOptions queryOptions,
+      AuthorizationConfig authzConfig) {
+    return feFixture_.createAnalysisCtx(queryOptions, authzConfig);
+  }
+
   protected AnalysisContext createAnalysisCtx(AuthorizationConfig authzConfig) {
     return feFixture_.createAnalysisCtx(authzConfig);
   }
diff --git a/fe/src/test/java/org/apache/impala/common/QueryFixture.java b/fe/src/test/java/org/apache/impala/common/QueryFixture.java
index 70db975..c72d9e7 100644
--- a/fe/src/test/java/org/apache/impala/common/QueryFixture.java
+++ b/fe/src/test/java/org/apache/impala/common/QueryFixture.java
@@ -33,7 +33,7 @@ import org.apache.impala.analysis.SqlScanner;
 import org.apache.impala.analysis.StatementBase;
 import org.apache.impala.analysis.StmtMetadataLoader;
 import org.apache.impala.analysis.StmtMetadataLoader.StmtTableCache;
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.testutil.TestUtils;
 import org.apache.impala.thrift.TQueryCtx;
 import org.apache.impala.thrift.TQueryOptions;
@@ -94,8 +94,7 @@ public class QueryFixture {
      */
     protected AnalysisContext makeAnalysisContext() {
       EventSequence timeline = new EventSequence("Frontend Test Timeline");
-      return new AnalysisContext(queryCtx_,
-          SentryAuthorizationConfig.createAuthDisabledConfig(), timeline);
+      return new AnalysisContext(queryCtx_, new NoneAuthorizationFactory(), timeline);
     }
 
     /**
diff --git a/fe/src/test/java/org/apache/impala/testutil/ImpaladTestCatalog.java b/fe/src/test/java/org/apache/impala/testutil/ImpaladTestCatalog.java
index 0b160e6..8128d34 100644
--- a/fe/src/test/java/org/apache/impala/testutil/ImpaladTestCatalog.java
+++ b/fe/src/test/java/org/apache/impala/testutil/ImpaladTestCatalog.java
@@ -20,6 +20,7 @@ package org.apache.impala.testutil;
 import com.google.common.base.Preconditions;
 import org.apache.impala.analysis.TableName;
 import org.apache.impala.authorization.AuthorizationConfig;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.catalog.BuiltinsDb;
 import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
 import org.apache.impala.catalog.CatalogException;
@@ -48,16 +49,17 @@ public class ImpaladTestCatalog extends ImpaladCatalog {
   private final CatalogServiceCatalog srcCatalog_;
 
   public ImpaladTestCatalog() {
-    this(SentryAuthorizationConfig.createAuthDisabledConfig());
+    this(new NoneAuthorizationFactory().getAuthorizationConfig());
   }
 
   /**
    * Takes an AuthorizationConfig to bootstrap the backing CatalogServiceCatalog.
    */
-  public ImpaladTestCatalog(SentryAuthorizationConfig authzConfig) {
+  public ImpaladTestCatalog(AuthorizationConfig authzConfig) {
     super("127.0.0.1");
     CatalogServiceCatalog catalogServerCatalog = authzConfig.isEnabled() ?
-        CatalogServiceTestCatalog.createWithAuth(authzConfig.getSentryConfig()) :
+        CatalogServiceTestCatalog.createWithAuth(
+            ((SentryAuthorizationConfig) authzConfig).getSentryConfig()) :
         CatalogServiceTestCatalog.create();
     authPolicy_ = catalogServerCatalog.getAuthPolicy();
     srcCatalog_ = catalogServerCatalog;
diff --git a/fe/src/test/java/org/apache/impala/testutil/PlannerTestCaseLoader.java b/fe/src/test/java/org/apache/impala/testutil/PlannerTestCaseLoader.java
index 9ae61fc..e612dcd 100644
--- a/fe/src/test/java/org/apache/impala/testutil/PlannerTestCaseLoader.java
+++ b/fe/src/test/java/org/apache/impala/testutil/PlannerTestCaseLoader.java
@@ -17,8 +17,7 @@
 
 package org.apache.impala.testutil;
 
-import org.apache.impala.authorization.AuthorizationConfig;
-import org.apache.impala.authorization.sentry.SentryAuthorizationConfig;
+import org.apache.impala.authorization.NoneAuthorizationFactory;
 import org.apache.impala.catalog.Catalog;
 import org.apache.impala.common.ImpalaException;
 import org.apache.impala.service.CatalogOpExecutor;
@@ -55,10 +54,9 @@ public class PlannerTestCaseLoader implements AutoCloseable {
   private final Frontend frontend_;
 
   public PlannerTestCaseLoader() throws ImpalaException {
-    AuthorizationConfig config = SentryAuthorizationConfig.createAuthDisabledConfig();
     catalog_ = new ImpaladTestCatalog(
         CatalogServiceTestCatalog.createTransientTestCatalog());
-    frontend_ = new Frontend(config, catalog_);
+    frontend_ = new Frontend(new NoneAuthorizationFactory(), catalog_);
     catalogOpExecutor_ = new CatalogOpExecutor(catalog_.getSrcCatalog());
   }