PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/release-0.1-rc2/hive/external/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/DefaultHiveAuthorizationProvider.java

#
Java | 495 lines | 360 code | 66 blank | 69 comment | 106 complexity | c39a276219cfa9aa5c7f08152bd28224 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, JSON, CPL-1.0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.hive.ql.security.authorization;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.HashSet;
  22. import java.util.List;
  23. import java.util.Set;
  24. import org.apache.hadoop.hive.metastore.api.Database;
  25. import org.apache.hadoop.hive.metastore.api.HiveObjectType;
  26. import org.apache.hadoop.hive.metastore.api.PrincipalPrivilegeSet;
  27. import org.apache.hadoop.hive.metastore.api.PrivilegeGrantInfo;
  28. import org.apache.hadoop.hive.ql.metadata.AuthorizationException;
  29. import org.apache.hadoop.hive.ql.metadata.HiveException;
  30. import org.apache.hadoop.hive.ql.metadata.Partition;
  31. import org.apache.hadoop.hive.ql.metadata.Table;
  32. public class DefaultHiveAuthorizationProvider extends
  33. HiveAuthorizationProviderBase {
  34. static class BitSetChecker {
  35. boolean[] inputCheck = null;
  36. boolean[] outputCheck = null;
  37. public static BitSetChecker getBitSetChecker(Privilege[] inputRequiredPriv,
  38. Privilege[] outputRequiredPriv) {
  39. BitSetChecker checker = new BitSetChecker();
  40. if (inputRequiredPriv != null) {
  41. checker.inputCheck = new boolean[inputRequiredPriv.length];
  42. for (int i = 0; i < checker.inputCheck.length; i++) {
  43. checker.inputCheck[i] = false;
  44. }
  45. }
  46. if (outputRequiredPriv != null) {
  47. checker.outputCheck = new boolean[outputRequiredPriv.length];
  48. for (int i = 0; i < checker.outputCheck.length; i++) {
  49. checker.outputCheck[i] = false;
  50. }
  51. }
  52. return checker;
  53. }
  54. }
  55. @Override
  56. public void authorize(Privilege[] inputRequiredPriv,
  57. Privilege[] outputRequiredPriv) throws HiveException, AuthorizationException {
  58. BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
  59. outputRequiredPriv);
  60. boolean[] inputCheck = checker.inputCheck;
  61. boolean[] outputCheck = checker.outputCheck;
  62. authorizeUserPriv(inputRequiredPriv, inputCheck, outputRequiredPriv,
  63. outputCheck);
  64. checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
  65. inputCheck, outputCheck, null, null, null, null);
  66. }
  67. @Override
  68. public void authorize(Database db, Privilege[] inputRequiredPriv,
  69. Privilege[] outputRequiredPriv) throws HiveException, AuthorizationException {
  70. BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
  71. outputRequiredPriv);
  72. boolean[] inputCheck = checker.inputCheck;
  73. boolean[] outputCheck = checker.outputCheck;
  74. authorizeUserAndDBPriv(db, inputRequiredPriv, outputRequiredPriv,
  75. inputCheck, outputCheck);
  76. checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
  77. inputCheck, outputCheck, db.getName(), null, null, null);
  78. }
  79. @Override
  80. public void authorize(Table table, Privilege[] inputRequiredPriv,
  81. Privilege[] outputRequiredPriv) throws HiveException {
  82. BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
  83. outputRequiredPriv);
  84. boolean[] inputCheck = checker.inputCheck;
  85. boolean[] outputCheck = checker.outputCheck;
  86. authorizeUserDBAndTable(table, inputRequiredPriv,
  87. outputRequiredPriv, inputCheck, outputCheck);
  88. checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
  89. inputCheck, outputCheck, table.getDbName(), table.getTableName(),
  90. null, null);
  91. }
  92. @Override
  93. public void authorize(Partition part, Privilege[] inputRequiredPriv,
  94. Privilege[] outputRequiredPriv) throws HiveException {
  95. //if the partition does not have partition level privilege, go to table level.
  96. Table table = part.getTable();
  97. if (table.getParameters().get("PARTITION_LEVEL_PRIVILEGE") == null || ("FALSE"
  98. .equalsIgnoreCase(table.getParameters().get(
  99. "PARTITION_LEVEL_PRIVILEGE")))) {
  100. this.authorize(part.getTable(), inputRequiredPriv, outputRequiredPriv);
  101. return;
  102. }
  103. BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
  104. outputRequiredPriv);
  105. boolean[] inputCheck = checker.inputCheck;
  106. boolean[] outputCheck = checker.outputCheck;
  107. if (authorizeUserDbAndPartition(part, inputRequiredPriv, outputRequiredPriv,
  108. inputCheck, outputCheck)){
  109. return;
  110. }
  111. checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
  112. inputCheck, outputCheck, part.getTable().getDbName(), part
  113. .getTable().getTableName(), part.getName(), null);
  114. }
  115. @Override
  116. public void authorize(Table table, Partition part, List<String> columns,
  117. Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv)
  118. throws HiveException {
  119. BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
  120. outputRequiredPriv);
  121. boolean[] inputCheck = checker.inputCheck;
  122. boolean[] outputCheck = checker.outputCheck;
  123. String partName = null;
  124. List<String> partValues = null;
  125. if (part != null
  126. && (table.getParameters().get("PARTITION_LEVEL_PRIVILEGE") != null && ("TRUE"
  127. .equalsIgnoreCase(table.getParameters().get(
  128. "PARTITION_LEVEL_PRIVILEGE"))))) {
  129. partName = part.getName();
  130. partValues = part.getValues();
  131. }
  132. if (partValues == null) {
  133. if (authorizeUserDBAndTable(table, inputRequiredPriv, outputRequiredPriv,
  134. inputCheck, outputCheck)) {
  135. return;
  136. }
  137. } else {
  138. if (authorizeUserDbAndPartition(part, inputRequiredPriv,
  139. outputRequiredPriv, inputCheck, outputCheck)) {
  140. return;
  141. }
  142. }
  143. for (String col : columns) {
  144. BitSetChecker checker2 = BitSetChecker.getBitSetChecker(
  145. inputRequiredPriv, outputRequiredPriv);
  146. boolean[] inputCheck2 = checker2.inputCheck;
  147. boolean[] outputCheck2 = checker2.outputCheck;
  148. PrincipalPrivilegeSet partColumnPrivileges = hive_db
  149. .get_privilege_set(HiveObjectType.COLUMN, table.getDbName(), table.getTableName(),
  150. partValues, col, this.getAuthenticator().getUserName(), this
  151. .getAuthenticator().getGroupNames());
  152. authorizePrivileges(partColumnPrivileges, inputRequiredPriv, inputCheck2,
  153. outputRequiredPriv, outputCheck2);
  154. if (inputCheck2 != null) {
  155. booleanArrayOr(inputCheck2, inputCheck);
  156. }
  157. if (outputCheck2 != null) {
  158. booleanArrayOr(inputCheck2, inputCheck);
  159. }
  160. checkAndThrowAuthorizationException(inputRequiredPriv,
  161. outputRequiredPriv, inputCheck2, outputCheck2, table.getDbName(),
  162. table.getTableName(), partName, col);
  163. }
  164. }
  165. protected boolean authorizeUserPriv(Privilege[] inputRequiredPriv,
  166. boolean[] inputCheck, Privilege[] outputRequiredPriv,
  167. boolean[] outputCheck) throws HiveException {
  168. PrincipalPrivilegeSet privileges = hive_db.get_privilege_set(
  169. HiveObjectType.GLOBAL, null, null, null, null, this.getAuthenticator()
  170. .getUserName(), this.getAuthenticator().getGroupNames());
  171. return authorizePrivileges(privileges, inputRequiredPriv, inputCheck,
  172. outputRequiredPriv, outputCheck);
  173. }
  174. /**
  175. * Check privileges on User and DB. This is used before doing a check on
  176. * table/partition objects, first check the user and DB privileges. If it
  177. * passed on this check, no need to check against the table/partition hive
  178. * object.
  179. *
  180. * @param db
  181. * @param inputRequiredPriv
  182. * @param outputRequiredPriv
  183. * @param inputCheck
  184. * @param outputCheck
  185. * @return true if the check on user and DB privilege passed, which means no
  186. * need for privilege check on concrete hive objects.
  187. * @throws HiveException
  188. */
  189. private boolean authorizeUserAndDBPriv(Database db,
  190. Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
  191. boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
  192. if (authorizeUserPriv(inputRequiredPriv, inputCheck, outputRequiredPriv,
  193. outputCheck)) {
  194. return true;
  195. }
  196. PrincipalPrivilegeSet dbPrivileges = hive_db.get_privilege_set(
  197. HiveObjectType.DATABASE, db.getName(), null, null, null, this
  198. .getAuthenticator().getUserName(), this.getAuthenticator()
  199. .getGroupNames());
  200. if (authorizePrivileges(dbPrivileges, inputRequiredPriv, inputCheck,
  201. outputRequiredPriv, outputCheck)) {
  202. return true;
  203. }
  204. return false;
  205. }
  206. /**
  207. * Check privileges on User, DB and table objects.
  208. *
  209. * @param table
  210. * @param inputRequiredPriv
  211. * @param outputRequiredPriv
  212. * @param inputCheck
  213. * @param outputCheck
  214. * @return true if the check passed
  215. * @throws HiveException
  216. */
  217. private boolean authorizeUserDBAndTable(Table table,
  218. Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
  219. boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
  220. if (authorizeUserAndDBPriv(hive_db.getDatabase(table.getDbName()),
  221. inputRequiredPriv, outputRequiredPriv, inputCheck, outputCheck)) {
  222. return true;
  223. }
  224. PrincipalPrivilegeSet tablePrivileges = hive_db.get_privilege_set(
  225. HiveObjectType.TABLE, table.getDbName(), table.getTableName(), null,
  226. null, this.getAuthenticator().getUserName(), this.getAuthenticator()
  227. .getGroupNames());
  228. if (authorizePrivileges(tablePrivileges, inputRequiredPriv, inputCheck,
  229. outputRequiredPriv, outputCheck)) {
  230. return true;
  231. }
  232. return false;
  233. }
  234. /**
  235. * Check privileges on User, DB and table/Partition objects.
  236. *
  237. * @param part
  238. * @param inputRequiredPriv
  239. * @param outputRequiredPriv
  240. * @param inputCheck
  241. * @param outputCheck
  242. * @return true if the check passed
  243. * @throws HiveException
  244. */
  245. private boolean authorizeUserDbAndPartition(Partition part,
  246. Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
  247. boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
  248. if (authorizeUserAndDBPriv(
  249. hive_db.getDatabase(part.getTable().getDbName()), inputRequiredPriv,
  250. outputRequiredPriv, inputCheck, outputCheck)) {
  251. return true;
  252. }
  253. PrincipalPrivilegeSet partPrivileges = part.getTPartition().getPrivileges();
  254. if (partPrivileges == null) {
  255. partPrivileges = hive_db.get_privilege_set(HiveObjectType.PARTITION, part
  256. .getTable().getDbName(), part.getTable().getTableName(), part
  257. .getValues(), null, this.getAuthenticator().getUserName(), this
  258. .getAuthenticator().getGroupNames());
  259. }
  260. if (authorizePrivileges(partPrivileges, inputRequiredPriv, inputCheck,
  261. outputRequiredPriv, outputCheck)) {
  262. return true;
  263. }
  264. return false;
  265. }
  266. protected boolean authorizePrivileges(PrincipalPrivilegeSet privileges,
  267. Privilege[] inputPriv, boolean[] inputCheck, Privilege[] outputPriv,
  268. boolean[] outputCheck) throws HiveException {
  269. boolean pass = true;
  270. if (inputPriv != null) {
  271. pass = pass && matchPrivs(inputPriv, privileges, inputCheck);
  272. }
  273. if (outputPriv != null) {
  274. pass = pass && matchPrivs(outputPriv, privileges, outputCheck);
  275. }
  276. return pass;
  277. }
  278. /**
  279. * try to match an array of privileges from user/groups/roles grants.
  280. *
  281. * @param container
  282. */
  283. private boolean matchPrivs(Privilege[] inputPriv,
  284. PrincipalPrivilegeSet privileges, boolean[] check) {
  285. if (inputPriv == null)
  286. return true;
  287. if (privileges == null)
  288. return false;
  289. /*
  290. * user grants
  291. */
  292. Set<String> privSet = new HashSet<String>();
  293. if (privileges.getUserPrivileges() != null
  294. && privileges.getUserPrivileges().size() > 0) {
  295. Collection<List<PrivilegeGrantInfo>> privCollection = privileges.getUserPrivileges().values();
  296. List<String> userPrivs = getPrivilegeStringList(privCollection);
  297. if (userPrivs != null && userPrivs.size() > 0) {
  298. for (String priv : userPrivs) {
  299. if (priv == null || priv.trim().equals(""))
  300. continue;
  301. if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
  302. setBooleanArray(check, true);
  303. return true;
  304. }
  305. privSet.add(priv.toLowerCase());
  306. }
  307. }
  308. }
  309. /*
  310. * group grants
  311. */
  312. if (privileges.getGroupPrivileges() != null
  313. && privileges.getGroupPrivileges().size() > 0) {
  314. Collection<List<PrivilegeGrantInfo>> groupPrivCollection = privileges
  315. .getGroupPrivileges().values();
  316. List<String> groupPrivs = getPrivilegeStringList(groupPrivCollection);
  317. if (groupPrivs != null && groupPrivs.size() > 0) {
  318. for (String priv : groupPrivs) {
  319. if (priv == null || priv.trim().equals(""))
  320. continue;
  321. if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
  322. setBooleanArray(check, true);
  323. return true;
  324. }
  325. privSet.add(priv.toLowerCase());
  326. }
  327. }
  328. }
  329. /*
  330. * roles grants
  331. */
  332. if (privileges.getRolePrivileges() != null
  333. && privileges.getRolePrivileges().size() > 0) {
  334. Collection<List<PrivilegeGrantInfo>> rolePrivsCollection = privileges
  335. .getRolePrivileges().values();
  336. ;
  337. List<String> rolePrivs = getPrivilegeStringList(rolePrivsCollection);
  338. if (rolePrivs != null && rolePrivs.size() > 0) {
  339. for (String priv : rolePrivs) {
  340. if (priv == null || priv.trim().equals(""))
  341. continue;
  342. if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
  343. setBooleanArray(check, true);
  344. return true;
  345. }
  346. privSet.add(priv.toLowerCase());
  347. }
  348. }
  349. }
  350. for (int i = 0; i < inputPriv.length; i++) {
  351. String toMatch = inputPriv[i].toString();
  352. if (!check[i]) {
  353. check[i] = privSet.contains(toMatch.toLowerCase());
  354. }
  355. }
  356. return firstFalseIndex(check) <0;
  357. }
  358. private List<String> getPrivilegeStringList(
  359. Collection<List<PrivilegeGrantInfo>> privCollection) {
  360. List<String> userPrivs = new ArrayList<String>();
  361. if (privCollection!= null && privCollection.size()>0) {
  362. for (List<PrivilegeGrantInfo> grantList : privCollection) {
  363. if (grantList == null){
  364. continue;
  365. }
  366. for (int i = 0; i < grantList.size(); i++) {
  367. PrivilegeGrantInfo grant = grantList.get(i);
  368. userPrivs.add(grant.getPrivilege());
  369. }
  370. }
  371. }
  372. return userPrivs;
  373. }
  374. private static void setBooleanArray(boolean[] check, boolean b) {
  375. for (int i = 0; i < check.length; i++) {
  376. check[i] = b;
  377. }
  378. }
  379. private static void booleanArrayOr(boolean[] output, boolean[] input) {
  380. for (int i = 0; i < output.length && i < input.length; i++) {
  381. output[i] = output[i] || input[i];
  382. }
  383. }
  384. private void checkAndThrowAuthorizationException(
  385. Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
  386. boolean[] inputCheck, boolean[] outputCheck,String dbName,
  387. String tableName, String partitionName, String columnName) {
  388. String hiveObject = "{ ";
  389. if (dbName != null) {
  390. hiveObject = hiveObject + "database:" + dbName;
  391. }
  392. if (tableName != null) {
  393. hiveObject = hiveObject + ", table:" + tableName;
  394. }
  395. if (partitionName != null) {
  396. hiveObject = hiveObject + ", partitionName:" + partitionName;
  397. }
  398. if (columnName != null) {
  399. hiveObject = hiveObject + ", columnName:" + columnName;
  400. }
  401. hiveObject = hiveObject + "}";
  402. if (inputCheck != null) {
  403. int input = this.firstFalseIndex(inputCheck);
  404. if (input >= 0) {
  405. throw new AuthorizationException("No privilege '"
  406. + inputRequiredPriv[input].toString() + "' found for inputs "
  407. + hiveObject);
  408. }
  409. }
  410. if (outputCheck != null) {
  411. int output = this.firstFalseIndex(outputCheck);
  412. if (output >= 0) {
  413. throw new AuthorizationException("No privilege '"
  414. + outputRequiredPriv[output].toString() + "' found for outputs "
  415. + hiveObject);
  416. }
  417. }
  418. }
  419. private int firstFalseIndex(boolean[] inputCheck) {
  420. if (inputCheck != null) {
  421. for (int i = 0; i < inputCheck.length; i++) {
  422. if (!inputCheck[i]) {
  423. return i;
  424. }
  425. }
  426. }
  427. return -1;
  428. }
  429. }