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());
}