diff --git itests/util/src/main/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidatorForTest.java itests/util/src/main/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidatorForTest.java index 41dd966..4003274 100644 --- itests/util/src/main/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidatorForTest.java +++ itests/util/src/main/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/SQLStdHiveAuthorizationValidatorForTest.java @@ -135,6 +135,9 @@ public boolean needTransform() { privObj .setRowFilterExpression("key in (select key from src where src.key = masking_test_subq.key)"); needRewritePrivObjs.add(privObj); + } else if (privObj.getObjectName().equals("masking_acid_no_masking")) { + // testing acid usage when no masking/filtering is present + needRewritePrivObjs.add(privObj); } } return needRewritePrivObjs; diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index 2430811..f765d99 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -10818,14 +10818,14 @@ private void walkASTMarkTABREF(ASTNode ast, Set cteAlias) .applyRowFilterAndColumnMasking(basicPrivObjs); if (needRewritePrivObjs != null && !needRewritePrivObjs.isEmpty()) { for (HivePrivilegeObject privObj : needRewritePrivObjs) { - // We don't support masking/filtering against ACID query at the moment - if (ctx.getIsUpdateDeleteMerge()) { - throw new SemanticException(ErrorMsg.MASKING_FILTERING_ON_ACID_NOT_SUPPORTED, - privObj.getDbname(), privObj.getObjectName()); - } MaskAndFilterInfo info = basicInfos.get(privObj); String replacementText = tableMask.create(privObj, info); if (replacementText != null) { + // We don't support masking/filtering against ACID query at the moment + if (ctx.getIsUpdateDeleteMerge()) { + throw new SemanticException(ErrorMsg.MASKING_FILTERING_ON_ACID_NOT_SUPPORTED, + privObj.getDbname(), privObj.getObjectName()); + } tableMask.setNeedsRewrite(true); tableMask.addTranslation(info.astNode, replacementText); } diff --git ql/src/test/queries/clientpositive/masking_acid_no_masking.q ql/src/test/queries/clientpositive/masking_acid_no_masking.q new file mode 100644 index 0000000..2d19826 --- /dev/null +++ ql/src/test/queries/clientpositive/masking_acid_no_masking.q @@ -0,0 +1,22 @@ +-- Simulate the case for org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizerFactory, +-- when all tables are marked eligible for masking. This shouldn't break any ACID operations. + +set hive.mapred.mode=nonstrict; +set hive.security.authorization.manager=org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactoryForTest; +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + +create table nonacid (key int, value string) stored as orc; + +create table masking_acid_no_masking (key int, value string) +clustered by (value) into 2 buckets stored as orc +tblproperties ("transactional"="true"); + +update masking_acid_no_masking set key=1 where value='ddd'; + +delete from masking_acid_no_masking where value='ddd'; + +MERGE INTO masking_acid_no_masking as t using nonacid as s ON t.key = s.key +WHEN MATCHED AND s.key < 5 THEN DELETE +WHEN MATCHED AND s.key < 3 THEN UPDATE set key = 1 +WHEN NOT MATCHED THEN INSERT VALUES (s.key, s.value); diff --git ql/src/test/results/clientpositive/masking_acid_no_masking.q.out ql/src/test/results/clientpositive/masking_acid_no_masking.q.out new file mode 100644 index 0000000..77f659f --- /dev/null +++ ql/src/test/results/clientpositive/masking_acid_no_masking.q.out @@ -0,0 +1,61 @@ +PREHOOK: query: create table nonacid (key int, value string) stored as orc +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@nonacid +POSTHOOK: query: create table nonacid (key int, value string) stored as orc +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@nonacid +PREHOOK: query: create table masking_acid_no_masking (key int, value string) +clustered by (value) into 2 buckets stored as orc +tblproperties ("transactional"="true") +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@masking_acid_no_masking +POSTHOOK: query: create table masking_acid_no_masking (key int, value string) +clustered by (value) into 2 buckets stored as orc +tblproperties ("transactional"="true") +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@masking_acid_no_masking +PREHOOK: query: update masking_acid_no_masking set key=1 where value='ddd' +PREHOOK: type: QUERY +PREHOOK: Input: default@masking_acid_no_masking +PREHOOK: Output: default@masking_acid_no_masking +POSTHOOK: query: update masking_acid_no_masking set key=1 where value='ddd' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@masking_acid_no_masking +POSTHOOK: Output: default@masking_acid_no_masking +PREHOOK: query: delete from masking_acid_no_masking where value='ddd' +PREHOOK: type: QUERY +PREHOOK: Input: default@masking_acid_no_masking +PREHOOK: Output: default@masking_acid_no_masking +POSTHOOK: query: delete from masking_acid_no_masking where value='ddd' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@masking_acid_no_masking +POSTHOOK: Output: default@masking_acid_no_masking +PREHOOK: query: MERGE INTO masking_acid_no_masking as t using nonacid as s ON t.key = s.key +WHEN MATCHED AND s.key < 5 THEN DELETE +WHEN MATCHED AND s.key < 3 THEN UPDATE set key = 1 +WHEN NOT MATCHED THEN INSERT VALUES (s.key, s.value) +PREHOOK: type: QUERY +PREHOOK: Input: default@masking_acid_no_masking +PREHOOK: Input: default@nonacid +PREHOOK: Output: default@masking_acid_no_masking +PREHOOK: Output: default@masking_acid_no_masking +PREHOOK: Output: default@masking_acid_no_masking +PREHOOK: Output: default@merge_tmp_table +POSTHOOK: query: MERGE INTO masking_acid_no_masking as t using nonacid as s ON t.key = s.key +WHEN MATCHED AND s.key < 5 THEN DELETE +WHEN MATCHED AND s.key < 3 THEN UPDATE set key = 1 +WHEN NOT MATCHED THEN INSERT VALUES (s.key, s.value) +POSTHOOK: type: QUERY +POSTHOOK: Input: default@masking_acid_no_masking +POSTHOOK: Input: default@nonacid +POSTHOOK: Output: default@masking_acid_no_masking +POSTHOOK: Output: default@masking_acid_no_masking +POSTHOOK: Output: default@masking_acid_no_masking +POSTHOOK: Output: default@merge_tmp_table +POSTHOOK: Lineage: masking_acid_no_masking.key SIMPLE [(nonacid)s.FieldSchema(name:key, type:int, comment:null), ] +POSTHOOK: Lineage: masking_acid_no_masking.value SIMPLE [(nonacid)s.FieldSchema(name:value, type:string, comment:null), ] +POSTHOOK: Lineage: merge_tmp_table.val EXPRESSION [(masking_acid_no_masking)t.FieldSchema(name:ROW__ID, type:struct, comment:), ]