View Javadoc

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  
19  package org.apache.hadoop.hbase.security.access;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.fail;
23  
24  import java.io.IOException;
25  import java.lang.reflect.UndeclaredThrowableException;
26  import java.security.PrivilegedActionException;
27  import java.security.PrivilegedExceptionAction;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.concurrent.Callable;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.conf.Configuration;
35  import org.apache.hadoop.hbase.Coprocessor;
36  import org.apache.hadoop.hbase.HBaseTestingUtility;
37  import org.apache.hadoop.hbase.HConstants;
38  import org.apache.hadoop.hbase.HTableDescriptor;
39  import org.apache.hadoop.hbase.MiniHBaseCluster;
40  import org.apache.hadoop.hbase.NamespaceDescriptor;
41  import org.apache.hadoop.hbase.TableName;
42  import org.apache.hadoop.hbase.Waiter.Predicate;
43  import org.apache.hadoop.hbase.client.HTable;
44  import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
45  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
46  import org.apache.hadoop.hbase.io.hfile.HFile;
47  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
48  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
49  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
50  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
51  import org.apache.hadoop.hbase.regionserver.HRegion;
52  import org.apache.hadoop.hbase.security.AccessDeniedException;
53  import org.apache.hadoop.hbase.security.User;
54  import org.apache.hadoop.hbase.security.access.Permission.Action;
55  import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
56  
57  import com.google.common.collect.Lists;
58  import com.google.common.collect.Maps;
59  import com.google.protobuf.BlockingRpcChannel;
60  import com.google.protobuf.ServiceException;
61  
62  /**
63   * Utility methods for testing security
64   */
65  public class SecureTestUtil {
66    
67    private static final Log LOG = LogFactory.getLog(SecureTestUtil.class);
68    private static final int WAIT_TIME = 10000;
69  
70    public static void configureSuperuser(Configuration conf) throws IOException {
71      // The secure minicluster creates separate service principals based on the
72      // current user's name, one for each slave. We need to add all of these to
73      // the superuser list or security won't function properly. We expect the
74      // HBase service account(s) to have superuser privilege.
75      String currentUser = User.getCurrent().getName();
76      StringBuffer sb = new StringBuffer();
77      sb.append("admin,");
78      sb.append(currentUser);
79      // Assumes we won't ever have a minicluster with more than 5 slaves
80      for (int i = 0; i < 5; i++) {
81        sb.append(',');
82        sb.append(currentUser); sb.append(".hfs."); sb.append(i);
83      }
84      conf.set("hbase.superuser", sb.toString());
85    }
86  
87    public static void enableSecurity(Configuration conf) throws IOException {
88      conf.set("hadoop.security.authorization", "false");
89      conf.set("hadoop.security.authentication", "simple");
90      conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, AccessController.class.getName());
91      conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName() +
92        "," + SecureBulkLoadEndpoint.class.getName());
93      conf.set(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName());
94      // Need HFile V3 for tags for security features
95      conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
96      configureSuperuser(conf);
97    }
98  
99    public static void verifyConfiguration(Configuration conf) {
100     String coprocs = conf.get(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY);
101     boolean accessControllerLoaded = false;
102     for (String coproc : coprocs.split(",")) {
103       try {
104         accessControllerLoaded = AccessController.class.isAssignableFrom(Class.forName(coproc));
105         if (accessControllerLoaded) break;
106       } catch (ClassNotFoundException cnfe) {
107       }
108     }
109     if (!(conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY).contains(
110         AccessController.class.getName())
111         && accessControllerLoaded && conf.get(
112         CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY).contains(
113         AccessController.class.getName()))) {
114       throw new RuntimeException("AccessController is missing from a system coprocessor list");
115     }
116     if (conf.getInt(HFile.FORMAT_VERSION_KEY, 2) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {
117       throw new RuntimeException("Post 0.96 security features require HFile version >= 3");
118     }
119   }
120 
121   public static void checkTablePerms(Configuration conf, byte[] table, byte[] family, byte[] column,
122       Permission.Action... actions) throws IOException {
123     Permission[] perms = new Permission[actions.length];
124     for (int i = 0; i < actions.length; i++) {
125       perms[i] = new TablePermission(TableName.valueOf(table), family, column, actions[i]);
126     }
127 
128     checkTablePerms(conf, table, perms);
129   }
130 
131   public static void checkTablePerms(Configuration conf, byte[] table, Permission... perms) throws IOException {
132     CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
133     for (Permission p : perms) {
134       request.addPermission(ProtobufUtil.toPermission(p));
135     }
136     HTable acl = new HTable(conf, table);
137     try {
138       AccessControlService.BlockingInterface protocol =
139         AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
140       try {
141         protocol.checkPermissions(null, request.build());
142       } catch (ServiceException se) {
143         ProtobufUtil.toIOException(se);
144       }
145     } finally {
146       acl.close();
147     }
148   }
149 
150   /**
151    * An AccessTestAction performs an action that will be examined to confirm
152    * the results conform to expected access rights.
153    * <p>
154    * To indicate an action was allowed, return null or a non empty list of
155    * KeyValues.
156    * <p>
157    * To indicate the action was not allowed, either throw an AccessDeniedException
158    * or return an empty list of KeyValues.
159    */
160   static interface AccessTestAction extends PrivilegedExceptionAction<Object> { }
161 
162   /** This fails only in case of ADE or empty list for any of the actions */
163   public static void verifyAllowed(User user, AccessTestAction... actions) throws Exception {
164     for (AccessTestAction action : actions) {
165       try {
166         Object obj = user.runAs(action);
167         if (obj != null && obj instanceof List<?>) {
168           List<?> results = (List<?>) obj;
169           if (results != null && results.isEmpty()) {
170             fail("Empty non null results from action for user '" + user.getShortName() + "'");
171           }
172         }
173       } catch (AccessDeniedException ade) {
174         fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
175       }
176     }
177   }
178 
179   /** This fails in case of ADE or empty list for any of the users. */
180   public static void verifyAllowed(AccessTestAction action, User... users) throws Exception {
181     for (User user : users) {
182       verifyAllowed(user, action);
183     }
184   }
185 
186   public static void verifyAllowed(User user, AccessTestAction action, int count) throws Exception {
187     try {
188       Object obj = user.runAs(action);
189       if (obj != null && obj instanceof List<?>) {
190         List<?> results = (List<?>) obj;
191         if (results != null && results.isEmpty()) {
192           fail("Empty non null results from action for user '" + user.getShortName() + "'");
193         }
194         assertEquals(count, results.size());
195       }
196     } catch (AccessDeniedException ade) {
197       fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
198     }
199   }
200 
201   /** This passes only in case of ADE for all users. */
202   public static void verifyDenied(AccessTestAction action, User... users) throws Exception {
203     for (User user : users) {
204       verifyDenied(user, action);
205     }
206   }
207 
208   /** This passes only in case of empty list for all users. */
209   public static void verifyIfEmptyList(AccessTestAction action, User... users) throws Exception {
210     for (User user : users) {
211       try {
212         Object obj = user.runAs(action);
213         if (obj != null && obj instanceof List<?>) {
214           List<?> results = (List<?>) obj;
215           if (results != null && !results.isEmpty()) {
216             fail("Unexpected action results: " +  results + " for user '"
217                 + user.getShortName() + "'");
218           }
219         } else {
220           fail("Unexpected results for user '" + user.getShortName() + "'");
221         }
222       } catch (AccessDeniedException ade) {
223         fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
224       }
225     }
226   }
227 
228   /** This passes only in case of null for all users. */
229   public static void verifyIfNull(AccessTestAction  action, User... users) throws Exception {
230     for (User user : users) {
231       try {
232         Object obj = user.runAs(action);
233         if (obj != null) {
234           fail("Non null results from action for user '" + user.getShortName() + "'");
235         }
236       } catch (AccessDeniedException ade) {
237         fail("Expected action to pass for user '" + user.getShortName() + "' but was denied");
238       }
239     }
240   }
241 
242   /** This passes only in case of ADE for all actions */
243   public static void verifyDenied(User user, AccessTestAction... actions) throws Exception {
244     for (AccessTestAction action : actions) {
245       try {
246         user.runAs(action);
247         fail("Expected exception was not thrown for user '" + user.getShortName() + "'");
248       } catch (IOException e) {
249         boolean isAccessDeniedException = false;
250         if(e instanceof RetriesExhaustedWithDetailsException) {
251           // in case of batch operations, and put, the client assembles a
252           // RetriesExhaustedWithDetailsException instead of throwing an
253           // AccessDeniedException
254           for(Throwable ex : ((RetriesExhaustedWithDetailsException) e).getCauses()) {
255             if (ex instanceof AccessDeniedException) {
256               isAccessDeniedException = true;
257               break;
258             }
259           }
260         }
261         else {
262           // For doBulkLoad calls AccessDeniedException
263           // is buried in the stack trace
264           Throwable ex = e;
265           do {
266             if (ex instanceof AccessDeniedException) {
267               isAccessDeniedException = true;
268               break;
269             }
270           } while((ex = ex.getCause()) != null);
271         }
272         if (!isAccessDeniedException) {
273           fail("Expected exception was not thrown for user '" + user.getShortName() + "'");
274         }
275       } catch (UndeclaredThrowableException ute) {
276         // TODO why we get a PrivilegedActionException, which is unexpected?
277         Throwable ex = ute.getUndeclaredThrowable();
278         if (ex instanceof PrivilegedActionException) {
279           ex = ((PrivilegedActionException) ex).getException();
280         }
281         if (ex instanceof ServiceException) {
282           ServiceException se = (ServiceException)ex;
283           if (se.getCause() != null && se.getCause() instanceof AccessDeniedException) {
284             // expected result
285             return;
286           }
287         }
288         fail("Expected exception was not thrown for user '" + user.getShortName() + "'");
289       }
290     }
291   }
292 
293   private static List<AccessController> getAccessControllers(MiniHBaseCluster cluster) {
294     List<AccessController> result = Lists.newArrayList();
295     for (RegionServerThread t: cluster.getLiveRegionServerThreads()) {
296       for (HRegion region: t.getRegionServer().getOnlineRegionsLocalContext()) {
297         Coprocessor cp = region.getCoprocessorHost()
298           .findCoprocessor(AccessController.class.getName());
299         if (cp != null) {
300           result.add((AccessController)cp);
301         }
302       }
303     }
304     return result;
305   }
306 
307   private static Map<AccessController,Long> getAuthManagerMTimes(MiniHBaseCluster cluster) {
308     Map<AccessController,Long> result = Maps.newHashMap();
309     for (AccessController ac: getAccessControllers(cluster)) {
310       result.put(ac, ac.getAuthManager().getMTime());
311     }
312     return result;
313   }
314 
315   @SuppressWarnings("rawtypes")
316   private static void updateACLs(final HBaseTestingUtility util, Callable c) throws Exception {
317     // Get the current mtimes for all access controllers
318     final Map<AccessController,Long> oldMTimes = getAuthManagerMTimes(util.getHBaseCluster());
319 
320     // Run the update action
321     c.call();
322 
323     // Wait until mtimes for all access controllers have incremented
324     util.waitFor(WAIT_TIME, 100, new Predicate<IOException>() {
325       @Override
326       public boolean evaluate() throws IOException {
327         Map<AccessController,Long> mtimes = getAuthManagerMTimes(util.getHBaseCluster());
328         for (Map.Entry<AccessController,Long> e: mtimes.entrySet()) {
329           if (!oldMTimes.containsKey(e.getKey())) {
330             LOG.error("Snapshot of AccessController state does not include instance on region " +
331               e.getKey().getRegion().getRegionNameAsString());
332             // Error out the predicate, we will try again
333             return false;
334           }
335           long old = oldMTimes.get(e.getKey());
336           long now = e.getValue();
337           if (now <= old) {
338             LOG.info("AccessController on region " +
339               e.getKey().getRegion().getRegionNameAsString() + " has not updated: mtime=" +
340               now);
341             return false;
342           }
343         }
344         return true;
345       }
346     });
347   }
348 
349   /**
350    * Grant permissions globally to the given user. Will wait until all active
351    * AccessController instances have updated their permissions caches or will
352    * throw an exception upon timeout (10 seconds).
353    */
354   public static void grantGlobal(final HBaseTestingUtility util, final String user,
355       final Permission.Action... actions) throws Exception {
356     SecureTestUtil.updateACLs(util, new Callable<Void>() {
357       @Override
358       public Void call() throws Exception {
359         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
360         try {
361           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
362           AccessControlService.BlockingInterface protocol =
363               AccessControlService.newBlockingStub(service);
364           ProtobufUtil.grant(protocol, user, actions);
365         } finally {
366           acl.close();
367         }
368         return null;
369       }
370     });
371   }
372 
373   /**
374    * Revoke permissions globally from the given user. Will wait until all active
375    * AccessController instances have updated their permissions caches or will
376    * throw an exception upon timeout (10 seconds).
377    */
378   public static void revokeGlobal(final HBaseTestingUtility util, final String user,
379       final Permission.Action... actions) throws Exception {
380     SecureTestUtil.updateACLs(util, new Callable<Void>() {
381       @Override
382       public Void call() throws Exception {
383         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
384         try {
385           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
386           AccessControlService.BlockingInterface protocol =
387               AccessControlService.newBlockingStub(service);
388           ProtobufUtil.revoke(protocol, user, actions);
389         } finally {
390           acl.close();
391         }
392         return null;
393       }
394     });
395   }
396 
397   /**
398    * Grant permissions on a namespace to the given user. Will wait until all active
399    * AccessController instances have updated their permissions caches or will
400    * throw an exception upon timeout (10 seconds).
401    */
402   public static void grantOnNamespace(final HBaseTestingUtility util, final String user,
403       final String namespace, final Permission.Action... actions) throws Exception {
404     SecureTestUtil.updateACLs(util, new Callable<Void>() {
405       @Override
406       public Void call() throws Exception {
407         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
408         try {
409           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
410           AccessControlService.BlockingInterface protocol =
411               AccessControlService.newBlockingStub(service);
412           ProtobufUtil.grant(protocol, user, namespace, actions);
413         } finally {
414           acl.close();
415         }
416         return null;
417       }
418     });
419   }
420 
421   /**
422    * Grant permissions on a namespace to the given user using AccessControl Client.
423    * Will wait until all active AccessController instances have updated their permissions caches
424    * or will throw an exception upon timeout (10 seconds).
425    */
426   public static void grantOnNamespaceUsingAccessControlClient(final HBaseTestingUtility util,
427       final Configuration conf, final String user, final String namespace,
428       final Permission.Action... actions) throws Exception {
429     SecureTestUtil.updateACLs(util, new Callable<Void>() {
430       @Override
431       public Void call() throws Exception {
432         try {
433           AccessControlClient.grant(conf, namespace, user, actions);
434         } catch (Throwable t) {
435           t.printStackTrace();
436         }
437         return null;
438       }
439     });
440   }
441 
442   /**
443    * Revoke permissions on a namespace from the given user using AccessControl Client.
444    * Will wait until all active AccessController instances have updated their permissions caches
445    * or will throw an exception upon timeout (10 seconds).
446    */
447   public static void revokeFromNamespaceUsingAccessControlClient(final HBaseTestingUtility util,
448       final Configuration conf, final String user, final String namespace,
449       final Permission.Action... actions) throws Exception {
450     SecureTestUtil.updateACLs(util, new Callable<Void>() {
451       @Override
452       public Void call() throws Exception {
453         try {
454           AccessControlClient.revoke(conf, namespace, user, actions);
455         } catch (Throwable t) {
456           t.printStackTrace();
457         }
458         return null;
459       }
460     });
461   }
462 
463   /**
464    * Revoke permissions on a namespace from the given user. Will wait until all active
465    * AccessController instances have updated their permissions caches or will
466    * throw an exception upon timeout (10 seconds).
467    */
468   public static void revokeFromNamespace(final HBaseTestingUtility util, final String user,
469       final String namespace, final Permission.Action... actions) throws Exception {
470     SecureTestUtil.updateACLs(util, new Callable<Void>() {
471       @Override
472       public Void call() throws Exception {
473         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
474         try {
475           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
476           AccessControlService.BlockingInterface protocol =
477               AccessControlService.newBlockingStub(service);
478           ProtobufUtil.revoke(protocol, user, namespace, actions);
479         } finally {
480           acl.close();
481         }
482         return null;
483       }
484     });
485   }
486 
487   /**
488    * Grant permissions on a table to the given user. Will wait until all active
489    * AccessController instances have updated their permissions caches or will
490    * throw an exception upon timeout (10 seconds).
491    */
492   public static void grantOnTable(final HBaseTestingUtility util, final String user,
493       final TableName table, final byte[] family, final byte[] qualifier,
494       final Permission.Action... actions) throws Exception {
495     SecureTestUtil.updateACLs(util, new Callable<Void>() {
496       @Override
497       public Void call() throws Exception {
498         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
499         try {
500           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
501           AccessControlService.BlockingInterface protocol =
502               AccessControlService.newBlockingStub(service);
503           ProtobufUtil.grant(protocol, user, table, family, qualifier, actions);
504         } finally {
505           acl.close();
506         }
507         return null;
508       }
509     });
510   }
511 
512   /**
513    * Grant permissions on a table to the given user using AccessControlClient. Will wait until all
514    * active AccessController instances have updated their permissions caches or will
515    * throw an exception upon timeout (10 seconds).
516    */
517   public static void grantOnTableUsingAccessControlClient(final HBaseTestingUtility util,
518       final Configuration conf, final String user, final TableName table, final byte[] family,
519       final byte[] qualifier, final Permission.Action... actions) throws Exception {
520     SecureTestUtil.updateACLs(util, new Callable<Void>() {
521       @Override
522       public Void call() throws Exception {
523         try {
524           AccessControlClient.grant(conf, table, user, family, qualifier, actions);
525         } catch (Throwable t) {
526           t.printStackTrace();
527         }
528         return null;
529       }
530     });
531   }
532 
533   /**
534    * Grant global permissions to the given user using AccessControlClient. Will wait until all
535    * active AccessController instances have updated their permissions caches or will
536    * throw an exception upon timeout (10 seconds).
537    */
538   public static void grantGlobalUsingAccessControlClient(final HBaseTestingUtility util,
539       final Configuration conf, final String user, final Permission.Action... actions)
540       throws Exception {
541     SecureTestUtil.updateACLs(util, new Callable<Void>() {
542       @Override
543       public Void call() throws Exception {
544         try {
545           AccessControlClient.grant(conf, user, actions);
546         } catch (Throwable t) {
547           t.printStackTrace();
548         }
549         return null;
550       }
551     });
552   }
553 
554   /**
555    * Revoke permissions on a table from the given user. Will wait until all active
556    * AccessController instances have updated their permissions caches or will
557    * throw an exception upon timeout (10 seconds).
558    */
559   public static void revokeFromTable(final HBaseTestingUtility util, final String user,
560       final TableName table, final byte[] family, final byte[] qualifier,
561       final Permission.Action... actions) throws Exception {
562     SecureTestUtil.updateACLs(util, new Callable<Void>() {
563       @Override
564       public Void call() throws Exception {
565         HTable acl = new HTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
566         try {
567           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
568           AccessControlService.BlockingInterface protocol =
569               AccessControlService.newBlockingStub(service);
570           ProtobufUtil.revoke(protocol, user, table, family, qualifier, actions);
571         } finally {
572           acl.close();
573         }
574         return null;
575       }
576     });
577   }
578 
579   /**
580    * Revoke permissions on a table from the given user using AccessControlClient. Will wait until
581    * all active AccessController instances have updated their permissions caches or will
582    * throw an exception upon timeout (10 seconds).
583    */
584   public static void revokeFromTableUsingAccessControlClient(final HBaseTestingUtility util,
585       final Configuration conf, final String user, final TableName table, final byte[] family,
586       final byte[] qualifier, final Permission.Action... actions) throws Exception {
587     SecureTestUtil.updateACLs(util, new Callable<Void>() {
588       @Override
589       public Void call() throws Exception {
590         try {
591           AccessControlClient.revoke(conf, table, user, family, qualifier, actions);
592         } catch (Throwable t) {
593           t.printStackTrace();
594         }
595         return null;
596       }
597     });
598   }
599 
600   /**
601    * Revoke global permissions from the given user using AccessControlClient. Will wait until
602    * all active AccessController instances have updated their permissions caches or will
603    * throw an exception upon timeout (10 seconds).
604    */
605   public static void revokeGlobalUsingAccessControlClient(final HBaseTestingUtility util,
606       final Configuration conf, final String user,final Permission.Action... actions)
607       throws Exception {
608     SecureTestUtil.updateACLs(util, new Callable<Void>() {
609       @Override
610       public Void call() throws Exception {
611         try {
612           AccessControlClient.revoke(conf, user, actions);
613         } catch (Throwable t) {
614           t.printStackTrace();
615         }
616         return null;
617       }
618     });
619   }
620 
621   public static void createNamespace(HBaseTestingUtility testUtil, NamespaceDescriptor nsDesc)
622       throws Exception {
623     testUtil.getHBaseAdmin().createNamespace(nsDesc);
624   }
625 
626   public static void deleteNamespace(HBaseTestingUtility testUtil, String namespace)
627       throws Exception {
628     testUtil.getHBaseAdmin().deleteNamespace(namespace);
629   }
630 
631   public static String convertToNamespace(String namespace) {
632     return AccessControlLists.NAMESPACE_PREFIX + namespace;
633   }
634 
635   public static void checkGlobalPerms(HBaseTestingUtility testUtil, Permission.Action... actions)
636       throws IOException {
637     Permission[] perms = new Permission[actions.length];
638     for (int i = 0; i < actions.length; i++) {
639       perms[i] = new Permission(actions[i]);
640     }
641     CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
642     for (Action a : actions) {
643       request.addPermission(AccessControlProtos.Permission.newBuilder()
644           .setType(AccessControlProtos.Permission.Type.Global)
645           .setGlobalPermission(
646               AccessControlProtos.GlobalPermission.newBuilder()
647                   .addAction(ProtobufUtil.toPermissionAction(a)).build()));
648     }
649     HTable acl = new HTable(testUtil.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
650     try {
651       BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
652       AccessControlService.BlockingInterface protocol =
653         AccessControlService.newBlockingStub(channel);
654       try {
655         protocol.checkPermissions(null, request.build());
656       } catch (ServiceException se) {
657         ProtobufUtil.toIOException(se);
658       }
659     } finally {
660       acl.close();
661     }
662   }
663 
664   public void checkTablePerms(HBaseTestingUtility testUtil, TableName table, byte[] family,
665       byte[] column, Permission.Action... actions) throws IOException {
666     Permission[] perms = new Permission[actions.length];
667     for (int i = 0; i < actions.length; i++) {
668       perms[i] = new TablePermission(table, family, column, actions[i]);
669     }
670     checkTablePerms(testUtil, table, perms);
671   }
672 
673   public void checkTablePerms(HBaseTestingUtility testUtil, TableName table, Permission... perms)
674       throws IOException {
675     CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
676     for (Permission p : perms) {
677       request.addPermission(ProtobufUtil.toPermission(p));
678     }
679     HTable acl = new HTable(testUtil.getConfiguration(), table);
680     try {
681       AccessControlService.BlockingInterface protocol =
682         AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
683       try {
684         protocol.checkPermissions(null, request.build());
685       } catch (ServiceException se) {
686         ProtobufUtil.toIOException(se);
687       }
688     } finally {
689       acl.close();
690     }
691   }
692 
693 }