PageRenderTime 75ms CodeModel.GetById 12ms app.highlight 58ms RepoModel.GetById 1ms 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
  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
 19package org.apache.hadoop.hive.ql.security.authorization;
 20
 21import java.util.ArrayList;
 22import java.util.Collection;
 23import java.util.HashSet;
 24import java.util.List;
 25import java.util.Set;
 26
 27import org.apache.hadoop.hive.metastore.api.Database;
 28import org.apache.hadoop.hive.metastore.api.HiveObjectType;
 29import org.apache.hadoop.hive.metastore.api.PrincipalPrivilegeSet;
 30import org.apache.hadoop.hive.metastore.api.PrivilegeGrantInfo;
 31import org.apache.hadoop.hive.ql.metadata.AuthorizationException;
 32import org.apache.hadoop.hive.ql.metadata.HiveException;
 33import org.apache.hadoop.hive.ql.metadata.Partition;
 34import org.apache.hadoop.hive.ql.metadata.Table;
 35
 36public class DefaultHiveAuthorizationProvider extends
 37    HiveAuthorizationProviderBase {
 38
 39  static class BitSetChecker {
 40
 41    boolean[] inputCheck = null;
 42    boolean[] outputCheck = null;
 43
 44    public static BitSetChecker getBitSetChecker(Privilege[] inputRequiredPriv,
 45        Privilege[] outputRequiredPriv) {
 46      BitSetChecker checker = new BitSetChecker();
 47      if (inputRequiredPriv != null) {
 48        checker.inputCheck = new boolean[inputRequiredPriv.length];
 49        for (int i = 0; i < checker.inputCheck.length; i++) {
 50          checker.inputCheck[i] = false;
 51        }
 52      }
 53      if (outputRequiredPriv != null) {
 54        checker.outputCheck = new boolean[outputRequiredPriv.length];
 55        for (int i = 0; i < checker.outputCheck.length; i++) {
 56          checker.outputCheck[i] = false;
 57        }
 58      }
 59
 60      return checker;
 61    }
 62
 63  }
 64
 65  @Override
 66  public void authorize(Privilege[] inputRequiredPriv,
 67      Privilege[] outputRequiredPriv) throws HiveException, AuthorizationException {
 68
 69    BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
 70        outputRequiredPriv);
 71    boolean[] inputCheck = checker.inputCheck;
 72    boolean[] outputCheck = checker.outputCheck;
 73
 74    authorizeUserPriv(inputRequiredPriv, inputCheck, outputRequiredPriv,
 75        outputCheck);
 76    checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
 77        inputCheck, outputCheck, null, null, null, null);
 78  }
 79  
 80  @Override
 81  public void authorize(Database db, Privilege[] inputRequiredPriv,
 82      Privilege[] outputRequiredPriv) throws HiveException, AuthorizationException {
 83
 84    BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
 85        outputRequiredPriv);
 86    boolean[] inputCheck = checker.inputCheck;
 87    boolean[] outputCheck = checker.outputCheck;
 88
 89    authorizeUserAndDBPriv(db, inputRequiredPriv, outputRequiredPriv,
 90        inputCheck, outputCheck);
 91    
 92    checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
 93        inputCheck, outputCheck, db.getName(), null, null, null);
 94  }
 95  
 96  @Override
 97  public void authorize(Table table, Privilege[] inputRequiredPriv,
 98      Privilege[] outputRequiredPriv) throws HiveException {
 99    BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
100        outputRequiredPriv);
101    boolean[] inputCheck = checker.inputCheck;
102    boolean[] outputCheck = checker.outputCheck;
103
104    authorizeUserDBAndTable(table, inputRequiredPriv,
105        outputRequiredPriv, inputCheck, outputCheck);
106    checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
107        inputCheck, outputCheck, table.getDbName(), table.getTableName(),
108        null, null);
109  }
110  
111  @Override
112  public void authorize(Partition part, Privilege[] inputRequiredPriv,
113      Privilege[] outputRequiredPriv) throws HiveException {
114
115    //if the partition does not have partition level privilege, go to table level.
116    Table table = part.getTable();
117    if (table.getParameters().get("PARTITION_LEVEL_PRIVILEGE") == null || ("FALSE"
118        .equalsIgnoreCase(table.getParameters().get(
119            "PARTITION_LEVEL_PRIVILEGE")))) {
120      this.authorize(part.getTable(), inputRequiredPriv, outputRequiredPriv);
121      return;
122    }
123    
124    BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
125        outputRequiredPriv);
126    boolean[] inputCheck = checker.inputCheck;
127    boolean[] outputCheck = checker.outputCheck;
128    
129    if (authorizeUserDbAndPartition(part, inputRequiredPriv, outputRequiredPriv,
130        inputCheck, outputCheck)){
131      return;
132    }
133
134    checkAndThrowAuthorizationException(inputRequiredPriv, outputRequiredPriv,
135        inputCheck, outputCheck, part.getTable().getDbName(), part
136            .getTable().getTableName(), part.getName(), null);
137  }
138
139  @Override
140  public void authorize(Table table, Partition part, List<String> columns,
141      Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv)
142      throws HiveException {
143    BitSetChecker checker = BitSetChecker.getBitSetChecker(inputRequiredPriv,
144        outputRequiredPriv);
145    boolean[] inputCheck = checker.inputCheck;
146    boolean[] outputCheck = checker.outputCheck;
147
148    String partName = null;
149    List<String> partValues = null;
150    if (part != null
151        && (table.getParameters().get("PARTITION_LEVEL_PRIVILEGE") != null && ("TRUE"
152            .equalsIgnoreCase(table.getParameters().get(
153                "PARTITION_LEVEL_PRIVILEGE"))))) {
154      partName = part.getName();
155      partValues = part.getValues();
156    }
157
158    if (partValues == null) {
159      if (authorizeUserDBAndTable(table, inputRequiredPriv, outputRequiredPriv,
160          inputCheck, outputCheck)) {
161        return;
162      }
163    } else {
164      if (authorizeUserDbAndPartition(part, inputRequiredPriv,
165          outputRequiredPriv, inputCheck, outputCheck)) {
166        return;
167      }
168    }
169
170    for (String col : columns) {
171      
172      BitSetChecker checker2 = BitSetChecker.getBitSetChecker(
173          inputRequiredPriv, outputRequiredPriv);
174      boolean[] inputCheck2 = checker2.inputCheck;
175      boolean[] outputCheck2 = checker2.outputCheck;
176
177      PrincipalPrivilegeSet partColumnPrivileges = hive_db
178          .get_privilege_set(HiveObjectType.COLUMN, table.getDbName(), table.getTableName(),
179              partValues, col, this.getAuthenticator().getUserName(), this
180                  .getAuthenticator().getGroupNames());
181      
182      authorizePrivileges(partColumnPrivileges, inputRequiredPriv, inputCheck2,
183          outputRequiredPriv, outputCheck2);
184  
185      if (inputCheck2 != null) {
186        booleanArrayOr(inputCheck2, inputCheck);
187      }
188      if (outputCheck2 != null) {
189        booleanArrayOr(inputCheck2, inputCheck);
190      }
191      
192      checkAndThrowAuthorizationException(inputRequiredPriv,
193          outputRequiredPriv, inputCheck2, outputCheck2, table.getDbName(),
194          table.getTableName(), partName, col);
195    }
196  }
197
198  protected boolean authorizeUserPriv(Privilege[] inputRequiredPriv,
199      boolean[] inputCheck, Privilege[] outputRequiredPriv,
200      boolean[] outputCheck) throws HiveException {
201    PrincipalPrivilegeSet privileges = hive_db.get_privilege_set(
202        HiveObjectType.GLOBAL, null, null, null, null, this.getAuthenticator()
203            .getUserName(), this.getAuthenticator().getGroupNames());
204    return authorizePrivileges(privileges, inputRequiredPriv, inputCheck,
205        outputRequiredPriv, outputCheck);
206  }
207
208  /**
209   * Check privileges on User and DB. This is used before doing a check on
210   * table/partition objects, first check the user and DB privileges. If it
211   * passed on this check, no need to check against the table/partition hive
212   * object.
213   * 
214   * @param db
215   * @param inputRequiredPriv
216   * @param outputRequiredPriv
217   * @param inputCheck
218   * @param outputCheck
219   * @return true if the check on user and DB privilege passed, which means no
220   *         need for privilege check on concrete hive objects.
221   * @throws HiveException
222   */
223  private boolean authorizeUserAndDBPriv(Database db,
224      Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
225      boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
226    if (authorizeUserPriv(inputRequiredPriv, inputCheck, outputRequiredPriv,
227        outputCheck)) {
228      return true;
229    }
230
231    PrincipalPrivilegeSet dbPrivileges = hive_db.get_privilege_set(
232        HiveObjectType.DATABASE, db.getName(), null, null, null, this
233            .getAuthenticator().getUserName(), this.getAuthenticator()
234            .getGroupNames());
235
236    if (authorizePrivileges(dbPrivileges, inputRequiredPriv, inputCheck,
237        outputRequiredPriv, outputCheck)) {
238      return true;
239    }
240
241    return false;
242  }
243
244  /**
245   * Check privileges on User, DB and table objects.
246   * 
247   * @param table
248   * @param inputRequiredPriv
249   * @param outputRequiredPriv
250   * @param inputCheck
251   * @param outputCheck
252   * @return true if the check passed
253   * @throws HiveException
254   */
255  private boolean authorizeUserDBAndTable(Table table,
256      Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
257      boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
258    
259    if (authorizeUserAndDBPriv(hive_db.getDatabase(table.getDbName()),
260        inputRequiredPriv, outputRequiredPriv, inputCheck, outputCheck)) {
261      return true;
262    }
263
264    PrincipalPrivilegeSet tablePrivileges = hive_db.get_privilege_set(
265        HiveObjectType.TABLE, table.getDbName(), table.getTableName(), null,
266        null, this.getAuthenticator().getUserName(), this.getAuthenticator()
267            .getGroupNames());
268
269    if (authorizePrivileges(tablePrivileges, inputRequiredPriv, inputCheck,
270        outputRequiredPriv, outputCheck)) {
271      return true;
272    }
273
274    return false;
275  }
276  
277  /**
278   * Check privileges on User, DB and table/Partition objects.
279   * 
280   * @param part
281   * @param inputRequiredPriv
282   * @param outputRequiredPriv
283   * @param inputCheck
284   * @param outputCheck
285   * @return true if the check passed
286   * @throws HiveException
287   */
288  private boolean authorizeUserDbAndPartition(Partition part,
289      Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
290      boolean[] inputCheck, boolean[] outputCheck) throws HiveException {
291
292    if (authorizeUserAndDBPriv(
293        hive_db.getDatabase(part.getTable().getDbName()), inputRequiredPriv,
294        outputRequiredPriv, inputCheck, outputCheck)) {
295      return true;
296    }
297
298    PrincipalPrivilegeSet partPrivileges = part.getTPartition().getPrivileges();
299    if (partPrivileges == null) {
300      partPrivileges = hive_db.get_privilege_set(HiveObjectType.PARTITION, part
301          .getTable().getDbName(), part.getTable().getTableName(), part
302          .getValues(), null, this.getAuthenticator().getUserName(), this
303          .getAuthenticator().getGroupNames());
304    }
305
306    if (authorizePrivileges(partPrivileges, inputRequiredPriv, inputCheck,
307        outputRequiredPriv, outputCheck)) {
308      return true;
309    }
310
311    return false;
312  }
313
314  protected boolean authorizePrivileges(PrincipalPrivilegeSet privileges,
315      Privilege[] inputPriv, boolean[] inputCheck, Privilege[] outputPriv,
316      boolean[] outputCheck) throws HiveException {
317
318    boolean pass = true;
319    if (inputPriv != null) {
320      pass = pass && matchPrivs(inputPriv, privileges, inputCheck);
321    }
322    if (outputPriv != null) {
323      pass = pass && matchPrivs(outputPriv, privileges, outputCheck);
324    }
325    return pass;
326  }
327
328  /**
329   * try to match an array of privileges from user/groups/roles grants.
330   * 
331   * @param container
332   */
333  private boolean matchPrivs(Privilege[] inputPriv,
334      PrincipalPrivilegeSet privileges, boolean[] check) {
335
336    if (inputPriv == null)
337      return true;
338    
339    if (privileges == null)
340      return false;
341
342    /*
343     * user grants
344     */
345    Set<String> privSet = new HashSet<String>();
346    if (privileges.getUserPrivileges() != null
347        && privileges.getUserPrivileges().size() > 0) {
348      Collection<List<PrivilegeGrantInfo>> privCollection = privileges.getUserPrivileges().values();
349      
350      List<String> userPrivs = getPrivilegeStringList(privCollection);
351      if (userPrivs != null && userPrivs.size() > 0) {
352        for (String priv : userPrivs) {
353          if (priv == null || priv.trim().equals(""))
354            continue;
355            if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
356              setBooleanArray(check, true);
357              return true;
358            }
359            privSet.add(priv.toLowerCase());
360        }
361      }
362    }
363
364    /*
365     * group grants
366     */
367    if (privileges.getGroupPrivileges() != null
368        && privileges.getGroupPrivileges().size() > 0) {
369      Collection<List<PrivilegeGrantInfo>> groupPrivCollection = privileges
370          .getGroupPrivileges().values();
371      List<String> groupPrivs = getPrivilegeStringList(groupPrivCollection);
372      if (groupPrivs != null && groupPrivs.size() > 0) {
373        for (String priv : groupPrivs) {
374          if (priv == null || priv.trim().equals(""))
375            continue;
376          if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
377            setBooleanArray(check, true);
378            return true;
379          }
380          privSet.add(priv.toLowerCase());
381        }
382      }
383    }
384
385    /*
386     * roles grants
387     */
388    if (privileges.getRolePrivileges() != null
389        && privileges.getRolePrivileges().size() > 0) {
390      Collection<List<PrivilegeGrantInfo>> rolePrivsCollection = privileges
391          .getRolePrivileges().values();
392      ;
393      List<String> rolePrivs = getPrivilegeStringList(rolePrivsCollection);
394      if (rolePrivs != null && rolePrivs.size() > 0) {
395        for (String priv : rolePrivs) {
396          if (priv == null || priv.trim().equals(""))
397            continue;
398          if (priv.equalsIgnoreCase(Privilege.ALL.toString())) {
399            setBooleanArray(check, true);
400            return true;
401          }
402          privSet.add(priv.toLowerCase());
403        }
404      }
405    }
406
407    for (int i = 0; i < inputPriv.length; i++) {
408      String toMatch = inputPriv[i].toString();
409      if (!check[i]) {
410        check[i] = privSet.contains(toMatch.toLowerCase());
411      }
412    }
413
414    return firstFalseIndex(check) <0;
415  }
416
417  private List<String> getPrivilegeStringList(
418      Collection<List<PrivilegeGrantInfo>> privCollection) {
419    List<String> userPrivs = new ArrayList<String>();
420    if (privCollection!= null && privCollection.size()>0) {
421      for (List<PrivilegeGrantInfo> grantList : privCollection) {
422        if (grantList == null){
423          continue;
424        }
425        for (int i = 0; i < grantList.size(); i++) {
426          PrivilegeGrantInfo grant = grantList.get(i);
427          userPrivs.add(grant.getPrivilege());
428        }
429      }        
430    }
431    return userPrivs;
432  }
433
434  private static void setBooleanArray(boolean[] check, boolean b) {
435    for (int i = 0; i < check.length; i++) {
436      check[i] = b;
437    }
438  }
439
440  private static void booleanArrayOr(boolean[] output, boolean[] input) {
441    for (int i = 0; i < output.length && i < input.length; i++) {
442      output[i] = output[i] || input[i];
443    }
444  }
445  
446  private void checkAndThrowAuthorizationException(
447      Privilege[] inputRequiredPriv, Privilege[] outputRequiredPriv,
448      boolean[] inputCheck, boolean[] outputCheck,String dbName,
449      String tableName, String partitionName, String columnName) {
450
451    String hiveObject = "{ ";
452    if (dbName != null) {
453      hiveObject = hiveObject + "database:" + dbName;
454    }
455    if (tableName != null) {
456      hiveObject = hiveObject + ", table:" + tableName;
457    }
458    if (partitionName != null) {
459      hiveObject = hiveObject + ", partitionName:" + partitionName;
460    }
461    if (columnName != null) {
462      hiveObject = hiveObject + ", columnName:" + columnName;
463    }
464    hiveObject = hiveObject + "}";
465
466    if (inputCheck != null) {
467      int input = this.firstFalseIndex(inputCheck);
468      if (input >= 0) {
469        throw new AuthorizationException("No privilege '"
470            + inputRequiredPriv[input].toString() + "' found for inputs "
471            + hiveObject);
472      }
473    }
474
475    if (outputCheck != null) {
476      int output = this.firstFalseIndex(outputCheck);
477      if (output >= 0) {
478        throw new AuthorizationException("No privilege '"
479            + outputRequiredPriv[output].toString() + "' found for outputs "
480            + hiveObject);
481      }
482    }
483  }
484
485  private int firstFalseIndex(boolean[] inputCheck) {
486    if (inputCheck != null) {
487      for (int i = 0; i < inputCheck.length; i++) {
488        if (!inputCheck[i]) {
489          return i;
490        }
491      }
492    }
493    return -1;
494  }
495}