diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java index 6d5c743..2009d11 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java @@ -172,9 +172,10 @@ public void testAuthZFailureLlapCachePurge() throws Exception { stmt.execute("llap cache -purge"); } catch (SQLException e) { caughtException = true; - String msg = "Error while processing statement: Permission denied: Principal [name=user1, type=USER] " + - "does not have following privileges for operation LLAP_CACHE [[ADMIN PRIVILEGE] on Object " + - "[type=COMMAND_PARAMS, name=[-purge]], [ADMIN PRIVILEGE] on Object [type=SERVICE_NAME, name=localhost]]"; + String msg = "Error while processing statement: Permission denied: Principal [name=user1, type=USER] does " + + "not have following privileges for operation LLAP_CACHE_PURGE [[ADMIN PRIVILEGE] on Object " + + "[type=COMMAND_PARAMS, name=[llap, cache, -purge]], [ADMIN PRIVILEGE] on Object " + + "[type=SERVICE_NAME, name=localhost]]"; assertEquals(msg, e.getMessage()); } finally { stmt.close(); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapCacheResourceProcessor.java b/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapCacheResourceProcessor.java index f455055..b11014c 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapCacheResourceProcessor.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapCacheResourceProcessor.java @@ -58,6 +58,7 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; +import com.google.common.collect.Lists; public class LlapCacheResourceProcessor implements CommandProcessor { public static final Logger LOG = LoggerFactory.getLogger(LlapCacheResourceProcessor.class); @@ -97,8 +98,10 @@ private CommandProcessorResponse llapCacheCommandHandler(final SessionState ss, hs2Host = ss.getHiveServer2Host(); } if (purge) { + List fullCommand = Lists.newArrayList("llap", "cache"); + fullCommand.addAll(Arrays.asList(params)); CommandProcessorResponse authErrResp = - CommandUtil.authorizeCommandAndServiceObject(ss, HiveOperationType.LLAP_CACHE, Arrays.asList(params), hs2Host); + CommandUtil.authorizeCommandAndServiceObject(ss, HiveOperationType.LLAP_CACHE_PURGE, fullCommand, hs2Host); if (authErrResp != null) { // there was an authorization issue return authErrResp; diff --git a/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapClusterResourceProcessor.java b/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapClusterResourceProcessor.java index 0238727..bd3c5ac 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapClusterResourceProcessor.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/processors/LlapClusterResourceProcessor.java @@ -24,6 +24,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; +import java.util.List; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -36,11 +37,13 @@ import org.apache.hadoop.hive.llap.registry.impl.LlapRegistryService; import org.apache.hadoop.hive.metastore.api.FieldSchema; import org.apache.hadoop.hive.metastore.api.Schema; +import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType; import org.apache.hadoop.hive.ql.session.SessionState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Joiner; +import com.google.common.collect.Lists; public class LlapClusterResourceProcessor implements CommandProcessor { public static final Logger LOG = LoggerFactory.getLogger(LlapClusterResourceProcessor.class); @@ -75,10 +78,22 @@ public CommandProcessorResponse run(String command) { private CommandProcessorResponse llapClusterCommandHandler(final SessionState ss, final String[] params) throws ParseException { CommandLine args = parseCommandArgs(CLUSTER_OPTIONS, params); + String hs2Host = null; + if (ss.isHiveServerQuery()) { + hs2Host = ss.getHiveServer2Host(); + } // no auth check for "LLAP CLUSTER INFO" boolean hasInfo = args.hasOption("info"); if (hasInfo) { + List fullCommand = Lists.newArrayList("llap", "cluster"); + fullCommand.addAll(Arrays.asList(params)); + CommandProcessorResponse authErrResp = + CommandUtil.authorizeCommandAndServiceObject(ss, HiveOperationType.LLAP_CLUSTER_INFO, fullCommand, hs2Host); + if (authErrResp != null) { + // there was an authorization issue + return authErrResp; + } try { LlapRegistryService llapRegistryService = LlapRegistryService.getClient(ss.getConf()); String appId = llapRegistryService.getApplicationId() == null ? "null" : diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java index 9e687ae..be5c062 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/HiveOperationType.java @@ -148,8 +148,8 @@ CREATE_MAPPING, ALTER_MAPPING, DROP_MAPPING, - LLAP_CLUSTER, - LLAP_CACHE, + LLAP_CLUSTER_INFO, + LLAP_CACHE_PURGE, // ==== Hive command operation types starts here ==== // SET, diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java index 71ff749..771dfb7 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java @@ -488,8 +488,11 @@ public HivePrivilegeObjectType getObjectType() { // Handled via adminPrivOps (see above). op2Priv.put(HiveOperationType.KILL_QUERY, PrivRequirement.newIOPrivRequirement(null, null)); - op2Priv.put(HiveOperationType.LLAP_CLUSTER, PrivRequirement.newIOPrivRequirement(null, null)); - op2Priv.put(HiveOperationType.LLAP_CACHE, PrivRequirement.newIOPrivRequirement(ADMIN_PRIV_AR, ADMIN_PRIV_AR)); + // llap cluster info does not need admin privilege, since it is read only assigning privilege same as + // describe/explain/show commands + op2Priv.put(HiveOperationType.LLAP_CLUSTER_INFO, PrivRequirement.newIOPrivRequirement(SEL_NOGRANT_AR, null)); + // llap cache purge requires admin privilege as it mutates state (cache) on the cluster + op2Priv.put(HiveOperationType.LLAP_CACHE_PURGE, PrivRequirement.newIOPrivRequirement(ADMIN_PRIV_AR, ADMIN_PRIV_AR)); op2Priv.put(HiveOperationType.CREATE_RESOURCEPLAN, PrivRequirement.newIOPrivRequirement(null, null)); op2Priv.put(HiveOperationType.ALTER_RESOURCEPLAN, PrivRequirement.newIOPrivRequirement(null, null)); op2Priv.put(HiveOperationType.DROP_RESOURCEPLAN, PrivRequirement.newIOPrivRequirement(null, null));