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/04/16 20:24:53 UTC
[impala] 02/05: IMPALA-6718: Add support for column-level
permissions on views
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 53798b0454332df44efce0032a88ef49e770a095
Author: Fredy Wijaya <fw...@cloudera.com>
AuthorDate: Mon Apr 8 14:08:38 2019 -0700
IMPALA-6718: Add support for column-level permissions on views
This patch adds support for column-level permissions on views. This
behavior is compatible with Hive column-level permissons on views. The
following statements are now supported.
GRANT select(col) ON db.my_view TO ROLE my_role -- Sentry only
REVOKE select(col) ON db.my_view FROM ROLE my_role -- Sentry only
GRANT select(col) ON db.my_view TO USER my_user -- Ranger only
REVOKE select(col) ON db.my_view FROM USER my_user -- Ranger only
GRANT select(col) ON db.my_view TO GROUP my_group -- Ranger only
REVOKE select(col) ON db.my_view FROM GROUP my_group -- Ranger only
Testing:
- Updated AuthorizationStmtTest to with new test cases
- Ran all FE tests
- Ran all E2E authorization tests
Change-Id: If81e683212cba22cc0fa5fc091ec3c799fa33e14
Reviewed-on: http://gerrit.cloudera.org:8080/12959
Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
.../org/apache/impala/analysis/PrivilegeSpec.java | 4 --
.../org/apache/impala/analysis/SelectStmt.java | 50 +++++++++++++++++++++
.../impala/analysis/AnalyzeAuthStmtsTest.java | 7 ++-
.../impala/analysis/AuthorizationStmtTest.java | 51 ++++++++++++----------
4 files changed, 82 insertions(+), 30 deletions(-)
diff --git a/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java b/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
index 9dd4168..e03c850 100644
--- a/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
+++ b/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
@@ -245,10 +245,6 @@ public class PrivilegeSpec extends StmtNode {
"in a column privilege spec.");
}
FeTable table = analyzeTargetTable(analyzer);
- if (table instanceof FeView) {
- throw new AnalysisException("Column-level privileges on views are not " +
- "supported.");
- }
if (table instanceof FeDataSourceTable) {
throw new AnalysisException("Column-level privileges on external data " +
"source tables are not supported.");
diff --git a/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java b/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
index 4cd1db0..580929e 100644
--- a/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/SelectStmt.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Set;
import org.apache.impala.analysis.Path.PathType;
+import org.apache.impala.authorization.Privilege;
import org.apache.impala.catalog.Column;
import org.apache.impala.catalog.FeTable;
import org.apache.impala.catalog.FeView;
@@ -208,6 +209,7 @@ public class SelectStmt extends QueryStmt {
analyzeSelectClause();
verifyResultExprs();
+ registerViewColumnPrivileges();
analyzeWhereClause();
createSortInfo(analyzer_);
@@ -538,6 +540,54 @@ public class SelectStmt extends QueryStmt {
}
/**
+ * Registers view column privileges only when the view a catalog view.
+ */
+ private void registerViewColumnPrivileges() {
+ for (TableRef tableRef: fromClause_.getTableRefs()) {
+ if (!(tableRef instanceof InlineViewRef)) continue;
+ InlineViewRef inlineViewRef = (InlineViewRef) tableRef;
+ FeView view = inlineViewRef.getView();
+ // For, local views (CTE), the view definition is explicitly defined in the query,
+ // this requires registering base column privileges instead of view column
+ // privileges. For example:
+ //
+ // with v as (select id as foo from functional.alltypes) select foo from v
+ //
+ // The query will register "functional.alltypes.id" column instead of
+ // "v.foo" column. This behavior is similar to inline views, e.g.
+ //
+ // select foo from (select id as foo from functional.alltypes) v
+ //
+ // The query will register "functional.alltypes.id" column instead of "v.foo"
+ // column.
+ //
+ // Contrasting this with catalog views.
+ //
+ // create view v(foo) as select id from functional.alltypes
+ // select v.foo from v
+ //
+ // The "select v.foo from v" query requires "v.foo" view column privilege because
+ // the "v" view definition is not exposed in the query. This behavior is also
+ // consistent with view access, such that the query requires a "select" privilege
+ // on "v" view and not "functional.alltypes" table.
+ boolean isCatalogView = view != null && !view.isLocalView();
+ if (!isCatalogView) continue;
+ for (Expr expr: getResultExprs()) {
+ List<Expr> slotRefs = new ArrayList<>();
+ expr.collectAll(Predicates.instanceOf(SlotRef.class), slotRefs);
+ for (Expr e: slotRefs) {
+ SlotRef slotRef = (SlotRef) e;
+ analyzer_.registerPrivReq(builder -> builder
+ .allOf(Privilege.SELECT)
+ .onColumn(view.getDb().getName(), view.getName(),
+ slotRef.getDesc().getLabel())
+ .build());
+ }
+ }
+ }
+ }
+
+ /**
* Analyze the HAVING clause. The HAVING clause is a predicate, not a list
* (like GROUP BY or ORDER BY) and so cannot contain ordinals.
*
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 1ff7033..8c44de7 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
@@ -233,6 +233,9 @@ public class AnalyzeAuthStmtsTest extends FrontendTestBase {
"alltypes %s %s", formatArgs), createAnalysisCtx("functional"));
AnalyzesOk(String.format("%s SELECT (id, bool_col) ON TABLE " +
"functional_kudu.alltypessmall %s %s", formatArgs));
+ // Column-level privileges on a VIEW
+ AnalyzesOk(String.format("%s SELECT (id, bool_col) ON TABLE " +
+ "functional.alltypes_hive_view %s %s", formatArgs));
// Empty column list
AnalysisError(String.format("%s SELECT () ON TABLE functional.alltypes " +
"%s %s", formatArgs), "Empty column list in column privilege spec.");
@@ -243,10 +246,6 @@ public class AnalyzeAuthStmtsTest extends FrontendTestBase {
AnalysisError(String.format("%s ALL (id, tinyint_col) ON TABLE " +
"functional.alltypes %s %s", formatArgs), "Only 'SELECT' privileges " +
"are allowed in a column privilege spec.");
- // Column-level privileges on a VIEW
- AnalysisError(String.format("%s SELECT (id, bool_col) ON TABLE " +
- "functional.alltypes_hive_view %s %s", formatArgs), "Column-level " +
- "privileges on views are not supported.");
// Columns/table that don't exist
AnalysisError(String.format("%s SELECT (invalid_col) ON TABLE " +
"functional.alltypes %s %s", formatArgs), "Error setting column-level " +
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 feb14f5..4fdfc92 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java
@@ -544,26 +544,30 @@ public class AuthorizationStmtTest extends FrontendTestBase {
// Select a specific column on a view.
- // Column-level privileges on views are not currently supported.
- authorize("select id from functional.alltypes_view")
- .ok(onServer(TPrivilegeLevel.ALL))
- .ok(onServer(TPrivilegeLevel.OWNER))
- .ok(onServer(TPrivilegeLevel.SELECT))
- .ok(onDatabase("functional", TPrivilegeLevel.ALL))
- .ok(onDatabase("functional", TPrivilegeLevel.OWNER))
- .ok(onDatabase("functional", TPrivilegeLevel.SELECT))
- .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
- .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
- .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT))
- .error(selectError("functional.alltypes_view"))
- .error(selectError("functional.alltypes_view"), onServer(allExcept(
- TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
- .error(selectError("functional.alltypes_view"), onDatabase("functional",
- allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
- TPrivilegeLevel.SELECT)))
- .error(selectError("functional.alltypes_view"), onTable("functional",
- "alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
- TPrivilegeLevel.SELECT)));
+ for (AuthzTest test: new AuthzTest[]{
+ authorize("select id from functional.alltypes_view"),
+ authorize("select 2 * v.id from functional.alltypes_view v"),
+ authorize("select cast(id as bigint) from functional.alltypes_view")}) {
+ test.ok(onServer(TPrivilegeLevel.ALL))
+ .ok(onServer(TPrivilegeLevel.OWNER))
+ .ok(onServer(TPrivilegeLevel.SELECT))
+ .ok(onDatabase("functional", TPrivilegeLevel.ALL))
+ .ok(onDatabase("functional", TPrivilegeLevel.OWNER))
+ .ok(onDatabase("functional", TPrivilegeLevel.SELECT))
+ .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL))
+ .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
+ .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT))
+ .ok(onColumn("functional", "alltypes_view", "id", TPrivilegeLevel.SELECT))
+ .error(selectError("functional.alltypes_view"))
+ .error(selectError("functional.alltypes_view"), onServer(allExcept(
+ TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
+ .error(selectError("functional.alltypes_view"), onDatabase("functional",
+ allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
+ TPrivilegeLevel.SELECT)))
+ .error(selectError("functional.alltypes_view"), onTable("functional",
+ "alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER,
+ TPrivilegeLevel.SELECT)));
+ }
// Constant select.
authorize("select 1").ok();
@@ -795,7 +799,6 @@ public class AuthorizationStmtTest extends FrontendTestBase {
}
// Union on views.
- // Column-level privileges on views are not currently supported.
authorize("select id from functional.alltypes_view union all " +
"select x from functional.alltypes_view_sub")
.ok(onServer(TPrivilegeLevel.ALL))
@@ -810,6 +813,8 @@ public class AuthorizationStmtTest extends FrontendTestBase {
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT),
onTable("functional", "alltypes_view_sub", TPrivilegeLevel.SELECT))
+ .ok(onColumn("functional", "alltypes_view", "id", TPrivilegeLevel.SELECT),
+ onColumn("functional", "alltypes_view_sub", "x", TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view"))
.error(selectError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.SELECT)))
@@ -902,7 +907,6 @@ public class AuthorizationStmtTest extends FrontendTestBase {
}
// Insert with select on a target view.
- // Column-level privileges on views are not currently supported.
authorize("insert into functional.alltypes partition(month, year) " +
"select * from functional.alltypes_view where id < 100")
.ok(onServer(TPrivilegeLevel.ALL))
@@ -917,6 +921,9 @@ public class AuthorizationStmtTest extends FrontendTestBase {
onTable("functional", "alltypes_view", TPrivilegeLevel.OWNER))
.ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT))
+ .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT),
+ onColumn("functional", "alltypes_view", ALLTYPES_COLUMNS,
+ TPrivilegeLevel.SELECT))
.error(selectError("functional.alltypes_view"))
.error(selectError("functional.alltypes_view"), onServer(allExcept(
TPrivilegeLevel.ALL, TPrivilegeLevel.OWNER, TPrivilegeLevel.INSERT,