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.apache.hadoop.hbase.AuthUtil.toGroupEntry;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.OutputStream;
31  import java.security.PrivilegedAction;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.List;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.hadoop.conf.Configuration;
39  import org.apache.hadoop.fs.FileStatus;
40  import org.apache.hadoop.fs.FileSystem;
41  import org.apache.hadoop.fs.Path;
42  import org.apache.hadoop.fs.permission.FsPermission;
43  import org.apache.hadoop.hbase.Coprocessor;
44  import org.apache.hadoop.hbase.CoprocessorEnvironment;
45  import org.apache.hadoop.hbase.HBaseIOException;
46  import org.apache.hadoop.hbase.HBaseTestingUtility;
47  import org.apache.hadoop.hbase.HColumnDescriptor;
48  import org.apache.hadoop.hbase.HConstants;
49  import org.apache.hadoop.hbase.HRegionInfo;
50  import org.apache.hadoop.hbase.HRegionLocation;
51  import org.apache.hadoop.hbase.HTableDescriptor;
52  import org.apache.hadoop.hbase.KeyValue;
53  import org.apache.hadoop.hbase.ProcedureInfo;
54  import org.apache.hadoop.hbase.security.Superusers;
55  import org.apache.hadoop.hbase.testclassification.LargeTests;
56  import org.apache.hadoop.hbase.MiniHBaseCluster;
57  import org.apache.hadoop.hbase.NamespaceDescriptor;
58  import org.apache.hadoop.hbase.ServerName;
59  import org.apache.hadoop.hbase.TableName;
60  import org.apache.hadoop.hbase.TableNotFoundException;
61  import org.apache.hadoop.hbase.Tag;
62  import org.apache.hadoop.hbase.client.Admin;
63  import org.apache.hadoop.hbase.client.Append;
64  import org.apache.hadoop.hbase.client.Connection;
65  import org.apache.hadoop.hbase.client.ConnectionFactory;
66  import org.apache.hadoop.hbase.client.Delete;
67  import org.apache.hadoop.hbase.client.Get;
68  import org.apache.hadoop.hbase.client.HTable;
69  import org.apache.hadoop.hbase.client.Increment;
70  import org.apache.hadoop.hbase.client.Put;
71  import org.apache.hadoop.hbase.client.RegionLocator;
72  import org.apache.hadoop.hbase.client.Result;
73  import org.apache.hadoop.hbase.client.ResultScanner;
74  import org.apache.hadoop.hbase.client.Scan;
75  import org.apache.hadoop.hbase.client.Table;
76  import org.apache.hadoop.hbase.client.security.SecurityCapability;
77  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
78  import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
79  import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
80  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
81  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
82  import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
83  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.CountRequest;
84  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.CountResponse;
85  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.HelloRequest;
86  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.HelloResponse;
87  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.IncrementCountRequest;
88  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.IncrementCountResponse;
89  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.NoopRequest;
90  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.NoopResponse;
91  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingRequest;
92  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingResponse;
93  import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingService;
94  import org.apache.hadoop.hbase.exceptions.HBaseException;
95  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
96  import org.apache.hadoop.hbase.io.hfile.HFile;
97  import org.apache.hadoop.hbase.io.hfile.HFileContext;
98  import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
99  import org.apache.hadoop.hbase.ipc.protobuf.generated.TestProcedureProtos;
100 import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
101 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
102 import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
103 import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface;
104 import org.apache.hadoop.hbase.procedure2.Procedure;
105 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
106 import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;
107 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
108 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
109 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
110 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
111 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
112 import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos.ProcedureState;
113 import org.apache.hadoop.hbase.regionserver.HRegion;
114 import org.apache.hadoop.hbase.regionserver.HRegionServer;
115 import org.apache.hadoop.hbase.regionserver.Region;
116 import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
117 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
118 import org.apache.hadoop.hbase.regionserver.ScanType;
119 import org.apache.hadoop.hbase.security.User;
120 import org.apache.hadoop.hbase.security.access.Permission.Action;
121 import org.apache.hadoop.hbase.util.Bytes;
122 import org.apache.hadoop.hbase.util.JVMClusterUtil;
123 import org.apache.log4j.Level;
124 import org.apache.log4j.Logger;
125 import org.junit.AfterClass;
126 import org.junit.BeforeClass;
127 import org.junit.Test;
128 import org.junit.experimental.categories.Category;
129 
130 import com.google.protobuf.BlockingRpcChannel;
131 import com.google.protobuf.RpcCallback;
132 import com.google.protobuf.RpcController;
133 import com.google.protobuf.Service;
134 import com.google.protobuf.ServiceException;
135 
136 /**
137  * Performs authorization checks for common operations, according to different
138  * levels of authorized users.
139  */
140 @Category(LargeTests.class)
141 public class TestAccessController extends SecureTestUtil {
142   private static final Log LOG = LogFactory.getLog(TestAccessController.class);
143 
144   static {
145     Logger.getLogger(AccessController.class).setLevel(Level.TRACE);
146     Logger.getLogger(AccessControlFilter.class).setLevel(Level.TRACE);
147     Logger.getLogger(TableAuthManager.class).setLevel(Level.TRACE);
148   }
149 
150   private static TableName TEST_TABLE = TableName.valueOf("testtable1");
151   private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
152   private static Configuration conf;
153 
154   /** The systemUserConnection created here is tied to the system user. In case, you are planning
155    * to create AccessTestAction, DON'T use this systemUserConnection as the 'doAs' user
156    * gets  eclipsed by the system user. */
157   private static Connection systemUserConnection;
158 
159 
160   // user with all permissions
161   private static User SUPERUSER;
162   // user granted with all global permission
163   private static User USER_ADMIN;
164   // user with rw permissions on column family.
165   private static User USER_RW;
166   // user with read-only permissions
167   private static User USER_RO;
168   // user is table owner. will have all permissions on table
169   private static User USER_OWNER;
170   // user with create table permissions alone
171   private static User USER_CREATE;
172   // user with no permissions
173   private static User USER_NONE;
174   // user with admin rights on the column family
175   private static User USER_ADMIN_CF;
176 
177   private static final String GROUP_ADMIN = "group_admin";
178   private static final String GROUP_CREATE = "group_create";
179   private static final String GROUP_READ = "group_read";
180   private static final String GROUP_WRITE = "group_write";
181 
182   private static User USER_GROUP_ADMIN;
183   private static User USER_GROUP_CREATE;
184   private static User USER_GROUP_READ;
185   private static User USER_GROUP_WRITE;
186 
187   // TODO: convert this test to cover the full matrix in
188   // https://hbase.apache.org/book/appendix_acl_matrix.html
189   // creating all Scope x Permission combinations
190 
191   private static TableName TEST_TABLE2 = TableName.valueOf("testtable2");
192   private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
193   private static byte[] TEST_QUALIFIER = Bytes.toBytes("q1");
194   private static byte[] TEST_ROW = Bytes.toBytes("r1");
195 
196   private static MasterCoprocessorEnvironment CP_ENV;
197   private static AccessController ACCESS_CONTROLLER;
198   private static RegionServerCoprocessorEnvironment RSCP_ENV;
199   private static RegionCoprocessorEnvironment RCP_ENV;
200 
201   @BeforeClass
202   public static void setupBeforeClass() throws Exception {
203     // setup configuration
204     conf = TEST_UTIL.getConfiguration();
205     // Up the handlers; this test needs more than usual.
206     conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
207     // Enable security
208     enableSecurity(conf);
209     // In this particular test case, we can't use SecureBulkLoadEndpoint because its doAs will fail
210     // to move a file for a random user
211     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName());
212     // Verify enableSecurity sets up what we require
213     verifyConfiguration(conf);
214 
215     // Enable EXEC permission checking
216     conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true);
217 
218     TEST_UTIL.startMiniCluster();
219     MasterCoprocessorHost cpHost =
220       TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
221     cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
222     ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
223     CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
224       Coprocessor.PRIORITY_HIGHEST, 1, conf);
225     RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
226       .getRegionServerCoprocessorHost();
227     RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
228       Coprocessor.PRIORITY_HIGHEST, 1, conf);
229 
230     // Wait for the ACL table to become available
231     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
232 
233     // create a set of test users
234     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
235     USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]);
236     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
237     USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
238     USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
239     USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]);
240     USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]);
241     USER_ADMIN_CF = User.createUserForTesting(conf, "col_family_admin", new String[0]);
242 
243     USER_GROUP_ADMIN =
244         User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN });
245     USER_GROUP_CREATE =
246         User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE });
247     USER_GROUP_READ =
248         User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ });
249     USER_GROUP_WRITE =
250         User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE });
251 
252     systemUserConnection = TEST_UTIL.getConnection();
253     setUpTableAndUserPermissions();
254   }
255 
256   @AfterClass
257   public static void tearDownAfterClass() throws Exception {
258     cleanUp();
259     TEST_UTIL.shutdownMiniCluster();
260   }
261 
262   private static void setUpTableAndUserPermissions() throws Exception {
263     HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
264     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
265     hcd.setMaxVersions(100);
266     htd.addFamily(hcd);
267     htd.setOwner(USER_OWNER);
268     createTable(TEST_UTIL, htd, new byte[][] { Bytes.toBytes("s") });
269 
270     Region region = TEST_UTIL.getHBaseCluster().getRegions(TEST_TABLE).get(0);
271     RegionCoprocessorHost rcpHost = region.getCoprocessorHost();
272     RCP_ENV = rcpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
273       Coprocessor.PRIORITY_HIGHEST, 1, conf);
274 
275     // Set up initial grants
276 
277     grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(),
278       Permission.Action.ADMIN,
279       Permission.Action.CREATE,
280       Permission.Action.READ,
281       Permission.Action.WRITE);
282 
283     grantOnTable(TEST_UTIL, USER_RW.getShortName(),
284       TEST_TABLE, TEST_FAMILY, null,
285       Permission.Action.READ,
286       Permission.Action.WRITE);
287 
288     // USER_CREATE is USER_RW plus CREATE permissions
289     grantOnTable(TEST_UTIL, USER_CREATE.getShortName(),
290       TEST_TABLE, null, null,
291       Permission.Action.CREATE,
292       Permission.Action.READ,
293       Permission.Action.WRITE);
294 
295     grantOnTable(TEST_UTIL, USER_RO.getShortName(),
296       TEST_TABLE, TEST_FAMILY, null,
297       Permission.Action.READ);
298 
299     grantOnTable(TEST_UTIL, USER_ADMIN_CF.getShortName(),
300       TEST_TABLE, TEST_FAMILY,
301       null, Permission.Action.ADMIN, Permission.Action.CREATE);
302 
303     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN);
304     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE);
305     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ);
306     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE);
307 
308     assertEquals(5, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size());
309     try {
310       assertEquals(5, AccessControlClient.getUserPermissions(systemUserConnection,
311           TEST_TABLE.toString()).size());
312     } catch (Throwable e) {
313       LOG.error("error during call of AccessControlClient.getUserPermissions. ", e);
314     }
315   }
316 
317   private static void cleanUp() throws Exception {
318     // Clean the _acl_ table
319     try {
320       deleteTable(TEST_UTIL, TEST_TABLE);
321     } catch (TableNotFoundException ex) {
322       // Test deleted the table, no problem
323       LOG.info("Test deleted table " + TEST_TABLE);
324     }
325     // Verify all table/namespace permissions are erased
326     assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size());
327     assertEquals(
328         0,
329         AccessControlLists.getNamespacePermissions(conf,
330             TEST_TABLE.getNamespaceAsString()).size());
331   }
332 
333   @Test (timeout=180000)
334   public void testSecurityCapabilities() throws Exception {
335     List<SecurityCapability> capabilities = TEST_UTIL.getConnection().getAdmin()
336       .getSecurityCapabilities();
337     assertTrue("AUTHORIZATION capability is missing",
338       capabilities.contains(SecurityCapability.AUTHORIZATION));
339     assertTrue("CELL_AUTHORIZATION capability is missing",
340       capabilities.contains(SecurityCapability.CELL_AUTHORIZATION));
341   }
342 
343   @Test (timeout=180000)
344   public void testTableCreate() throws Exception {
345     AccessTestAction createTable = new AccessTestAction() {
346       @Override
347       public Object run() throws Exception {
348         HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("testnewtable"));
349         htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
350         ACCESS_CONTROLLER.preCreateTable(ObserverContext.createAndPrepare(CP_ENV, null), htd, null);
351         return null;
352       }
353     };
354 
355     // verify that superuser can create tables
356     verifyAllowed(createTable, SUPERUSER, USER_ADMIN, USER_GROUP_CREATE);
357 
358     // all others should be denied
359     verifyDenied(createTable, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_ADMIN,
360       USER_GROUP_READ, USER_GROUP_WRITE);
361   }
362 
363   @Test (timeout=180000)
364   public void testTableModify() throws Exception {
365     AccessTestAction modifyTable = new AccessTestAction() {
366       @Override
367       public Object run() throws Exception {
368         HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
369         htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
370         htd.addFamily(new HColumnDescriptor("fam_" + User.getCurrent().getShortName()));
371         ACCESS_CONTROLLER.preModifyTable(ObserverContext.createAndPrepare(CP_ENV, null),
372           TEST_TABLE, htd);
373         return null;
374       }
375     };
376 
377     verifyAllowed(modifyTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
378       USER_GROUP_ADMIN);
379     verifyDenied(modifyTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
380   }
381 
382   @Test (timeout=180000)
383   public void testTableDelete() throws Exception {
384     AccessTestAction deleteTable = new AccessTestAction() {
385       @Override
386       public Object run() throws Exception {
387         ACCESS_CONTROLLER
388             .preDeleteTable(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE);
389         return null;
390       }
391     };
392 
393     verifyAllowed(deleteTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
394       USER_GROUP_ADMIN);
395     verifyDenied(deleteTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
396   }
397 
398   @Test (timeout=180000)
399   public void testTableTruncate() throws Exception {
400     AccessTestAction truncateTable = new AccessTestAction() {
401       @Override
402       public Object run() throws Exception {
403         ACCESS_CONTROLLER
404             .preTruncateTable(ObserverContext.createAndPrepare(CP_ENV, null),
405                 TEST_TABLE);
406         return null;
407       }
408     };
409 
410     verifyAllowed(truncateTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
411       USER_GROUP_ADMIN);
412     verifyDenied(truncateTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
413   }
414 
415   @Test (timeout=180000)
416   public void testAddColumn() throws Exception {
417     final HColumnDescriptor hcd = new HColumnDescriptor("fam_new");
418     AccessTestAction action = new AccessTestAction() {
419       @Override
420       public Object run() throws Exception {
421         ACCESS_CONTROLLER.preAddColumn(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE,
422             hcd);
423         return null;
424       }
425     };
426 
427     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
428       USER_GROUP_ADMIN);
429     verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
430   }
431 
432   @Test (timeout=180000)
433   public void testModifyColumn() throws Exception {
434     final HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
435     hcd.setMaxVersions(10);
436     AccessTestAction action = new AccessTestAction() {
437       @Override
438       public Object run() throws Exception {
439         ACCESS_CONTROLLER.preModifyColumn(ObserverContext.createAndPrepare(CP_ENV, null),
440             TEST_TABLE, hcd);
441         return null;
442       }
443     };
444 
445     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_ADMIN_CF,
446       USER_GROUP_CREATE, USER_GROUP_ADMIN);
447     verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
448   }
449 
450   @Test (timeout=180000)
451   public void testDeleteColumn() throws Exception {
452     AccessTestAction action = new AccessTestAction() {
453       @Override
454       public Object run() throws Exception {
455         ACCESS_CONTROLLER.preDeleteColumn(ObserverContext.createAndPrepare(CP_ENV, null),
456             TEST_TABLE, TEST_FAMILY);
457         return null;
458       }
459     };
460 
461     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_ADMIN_CF,
462       USER_GROUP_CREATE, USER_GROUP_ADMIN);
463     verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
464   }
465 
466   @Test (timeout=180000)
467   public void testTableDisable() throws Exception {
468     AccessTestAction disableTable = new AccessTestAction() {
469       @Override
470       public Object run() throws Exception {
471         ACCESS_CONTROLLER.preDisableTable(ObserverContext.createAndPrepare(CP_ENV, null),
472           TEST_TABLE);
473         return null;
474       }
475     };
476 
477     AccessTestAction disableAclTable = new AccessTestAction() {
478       @Override
479       public Object run() throws Exception {
480         ACCESS_CONTROLLER.preDisableTable(ObserverContext.createAndPrepare(CP_ENV, null),
481             AccessControlLists.ACL_TABLE_NAME);
482         return null;
483       }
484     };
485 
486     verifyAllowed(disableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
487       USER_GROUP_ADMIN);
488     verifyDenied(disableTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
489 
490     // No user should be allowed to disable _acl_ table
491     verifyDenied(disableAclTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
492       USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_WRITE);
493   }
494 
495   @Test (timeout=180000)
496   public void testTableEnable() throws Exception {
497     AccessTestAction enableTable = new AccessTestAction() {
498       @Override
499       public Object run() throws Exception {
500         ACCESS_CONTROLLER
501             .preEnableTable(ObserverContext.createAndPrepare(CP_ENV, null), TEST_TABLE);
502         return null;
503       }
504     };
505 
506     verifyAllowed(enableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE,
507       USER_GROUP_ADMIN);
508     verifyDenied(enableTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
509   }
510 
511   public static class TestTableDDLProcedure extends Procedure<MasterProcedureEnv>
512   implements TableProcedureInterface {
513     private TableName tableName;
514 
515     public TestTableDDLProcedure() {
516     }
517 
518     public TestTableDDLProcedure(final MasterProcedureEnv env, final TableName tableName)
519         throws IOException {
520       this.tableName = tableName;
521       this.setTimeout(180000); // Timeout in 3 minutes
522       this.setOwner(env.getRequestUser().getUGI().getShortUserName());
523     }
524 
525     @Override
526     public TableName getTableName() {
527       return tableName;
528     }
529 
530     @Override
531     public TableOperationType getTableOperationType() {
532       return null;
533     }
534 
535     @Override
536     protected boolean abort(MasterProcedureEnv env) {
537       return true;
538     }
539 
540     @Override
541     protected void serializeStateData(OutputStream stream) throws IOException {
542       TestProcedureProtos.TestTableDDLStateData.Builder testTableDDLMsg =
543           TestProcedureProtos.TestTableDDLStateData.newBuilder()
544           .setTableName(tableName.getNameAsString());
545       testTableDDLMsg.build().writeDelimitedTo(stream);
546     }
547 
548     @Override
549     protected void deserializeStateData(InputStream stream) throws IOException {
550       TestProcedureProtos.TestTableDDLStateData testTableDDLMsg =
551           TestProcedureProtos.TestTableDDLStateData.parseDelimitedFrom(stream);
552       tableName = TableName.valueOf(testTableDDLMsg.getTableName());
553     }
554 
555     @Override
556     protected Procedure[] execute(MasterProcedureEnv env) throws ProcedureYieldException,
557         InterruptedException {
558       // Not letting the procedure to complete until timed out
559       setState(ProcedureState.WAITING_TIMEOUT);
560       return null;
561     }
562 
563     @Override
564     protected void rollback(MasterProcedureEnv env) throws IOException, InterruptedException {
565     }
566   }
567 
568   @Test
569   public void testAbortProcedure() throws Exception {
570     final TableName tableName = TableName.valueOf("testAbortProcedure");
571     final ProcedureExecutor<MasterProcedureEnv> procExec =
572         TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
573     Procedure proc = new TestTableDDLProcedure(procExec.getEnvironment(), tableName);
574     proc.setOwner(USER_OWNER.getShortName());
575     final long procId = procExec.submitProcedure(proc);
576 
577     AccessTestAction abortProcedureAction = new AccessTestAction() {
578       @Override
579       public Object run() throws Exception {
580         ACCESS_CONTROLLER
581         .preAbortProcedure(ObserverContext.createAndPrepare(CP_ENV, null), procExec, procId);
582        return null;
583       }
584     };
585 
586     verifyAllowed(abortProcedureAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
587     verifyAllowed(abortProcedureAction, USER_OWNER);
588     verifyDenied(
589       abortProcedureAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
590   }
591 
592   @Test
593   public void testListProcedures() throws Exception {
594     final TableName tableName = TableName.valueOf("testAbortProcedure");
595     final ProcedureExecutor<MasterProcedureEnv> procExec =
596         TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
597     Procedure proc = new TestTableDDLProcedure(procExec.getEnvironment(), tableName);
598     proc.setOwner(USER_OWNER.getShortName());
599     final long procId = procExec.submitProcedure(proc);
600     final List<ProcedureInfo> procInfoList = procExec.listProcedures();
601 
602     AccessTestAction listProceduresAction = new AccessTestAction() {
603       @Override
604       public Object run() throws Exception {
605         List<ProcedureInfo> procInfoListClone = new ArrayList<ProcedureInfo>(procInfoList.size());
606         for(ProcedureInfo pi : procInfoList) {
607           procInfoListClone.add(pi.clone());
608         }
609         ACCESS_CONTROLLER
610         .postListProcedures(ObserverContext.createAndPrepare(CP_ENV, null), procInfoListClone);
611        return null;
612       }
613     };
614 
615     verifyAllowed(listProceduresAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
616     verifyAllowed(listProceduresAction, USER_OWNER);
617     verifyIfNull(
618       listProceduresAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
619   }
620 
621   @Test (timeout=180000)
622   public void testMove() throws Exception {
623     List<HRegionLocation> regions;
624     try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) {
625       regions = locator.getAllRegionLocations();
626     }
627     HRegionLocation location = regions.get(0);
628     final HRegionInfo hri = location.getRegionInfo();
629     final ServerName server = location.getServerName();
630     AccessTestAction action = new AccessTestAction() {
631       @Override
632       public Object run() throws Exception {
633         ACCESS_CONTROLLER.preMove(ObserverContext.createAndPrepare(CP_ENV, null),
634             hri, server, server);
635         return null;
636       }
637     };
638 
639     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
640     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
641       USER_GROUP_WRITE, USER_GROUP_CREATE);
642   }
643 
644   @Test (timeout=180000)
645   public void testAssign() throws Exception {
646     List<HRegionLocation> regions;
647     try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) {
648       regions = locator.getAllRegionLocations();
649     }
650     HRegionLocation location = regions.get(0);
651     final HRegionInfo hri = location.getRegionInfo();
652     AccessTestAction action = new AccessTestAction() {
653       @Override
654       public Object run() throws Exception {
655         ACCESS_CONTROLLER.preAssign(ObserverContext.createAndPrepare(CP_ENV, null), hri);
656         return null;
657       }
658     };
659 
660     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
661     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
662       USER_GROUP_WRITE, USER_GROUP_CREATE);
663   }
664 
665   @Test (timeout=180000)
666   public void testUnassign() throws Exception {
667     List<HRegionLocation> regions;
668     try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) {
669       regions = locator.getAllRegionLocations();
670     }
671     HRegionLocation location = regions.get(0);
672     final HRegionInfo hri = location.getRegionInfo();
673     AccessTestAction action = new AccessTestAction() {
674       @Override
675       public Object run() throws Exception {
676         ACCESS_CONTROLLER.preUnassign(ObserverContext.createAndPrepare(CP_ENV, null), hri, false);
677         return null;
678       }
679     };
680 
681     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
682     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
683       USER_GROUP_WRITE, USER_GROUP_CREATE);
684   }
685 
686   @Test (timeout=180000)
687   public void testRegionOffline() throws Exception {
688     List<HRegionLocation> regions;
689     try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) {
690       regions = locator.getAllRegionLocations();
691     }
692     HRegionLocation location = regions.get(0);
693     final HRegionInfo hri = location.getRegionInfo();
694     AccessTestAction action = new AccessTestAction() {
695       @Override
696       public Object run() throws Exception {
697         ACCESS_CONTROLLER.preRegionOffline(ObserverContext.createAndPrepare(CP_ENV, null), hri);
698         return null;
699       }
700     };
701 
702     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
703     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
704       USER_GROUP_WRITE, USER_GROUP_CREATE);
705   }
706 
707   @Test (timeout=180000)
708   public void testBalance() throws Exception {
709     AccessTestAction action = new AccessTestAction() {
710       @Override
711       public Object run() throws Exception {
712         ACCESS_CONTROLLER.preBalance(ObserverContext.createAndPrepare(CP_ENV, null));
713         return null;
714       }
715     };
716 
717     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
718     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
719       USER_GROUP_WRITE, USER_GROUP_CREATE);
720   }
721 
722   @Test (timeout=180000)
723   public void testBalanceSwitch() throws Exception {
724     AccessTestAction action = new AccessTestAction() {
725       @Override
726       public Object run() throws Exception {
727         ACCESS_CONTROLLER.preBalanceSwitch(ObserverContext.createAndPrepare(CP_ENV, null), true);
728         return null;
729       }
730     };
731 
732     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
733     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
734       USER_GROUP_WRITE, USER_GROUP_CREATE);
735   }
736 
737   @Test (timeout=180000)
738   public void testShutdown() throws Exception {
739     AccessTestAction action = new AccessTestAction() {
740       @Override
741       public Object run() throws Exception {
742         ACCESS_CONTROLLER.preShutdown(ObserverContext.createAndPrepare(CP_ENV, null));
743         return null;
744       }
745     };
746 
747     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
748     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
749       USER_GROUP_WRITE, USER_GROUP_CREATE);
750   }
751 
752   @Test (timeout=180000)
753   public void testStopMaster() throws Exception {
754     AccessTestAction action = new AccessTestAction() {
755       @Override
756       public Object run() throws Exception {
757         ACCESS_CONTROLLER.preStopMaster(ObserverContext.createAndPrepare(CP_ENV, null));
758         return null;
759       }
760     };
761 
762     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
763     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
764       USER_GROUP_WRITE, USER_GROUP_CREATE);
765   }
766 
767   private void verifyWrite(AccessTestAction action) throws Exception {
768     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
769       USER_GROUP_WRITE);
770     verifyDenied(action, USER_NONE, USER_RO, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_CREATE);
771   }
772 
773   @Test (timeout=180000)
774   public void testSplit() throws Exception {
775     AccessTestAction action = new AccessTestAction() {
776       @Override
777       public Object run() throws Exception {
778         ACCESS_CONTROLLER.preSplit(ObserverContext.createAndPrepare(RCP_ENV, null));
779         return null;
780       }
781     };
782 
783     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
784     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
785       USER_GROUP_WRITE, USER_GROUP_CREATE);
786   }
787 
788   @Test (timeout=180000)
789   public void testSplitWithSplitRow() throws Exception {
790     AccessTestAction action = new AccessTestAction() {
791       @Override
792       public Object run() throws Exception {
793         ACCESS_CONTROLLER.preSplit(
794             ObserverContext.createAndPrepare(RCP_ENV, null),
795             TEST_ROW);
796         return null;
797       }
798     };
799 
800     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
801     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
802       USER_GROUP_WRITE, USER_GROUP_CREATE);
803   }
804 
805   @Test (timeout=180000)
806   public void testMergeRegions() throws Exception {
807     final TableName tname = TableName.valueOf("testMergeRegions");
808     createTestTable(tname);
809     try {
810       final List<HRegion> regions = TEST_UTIL.getHBaseCluster().findRegionsForTable(tname);
811       assertTrue("not enough regions: " + regions.size(), regions.size() >= 2);
812 
813       AccessTestAction action = new AccessTestAction() {
814         @Override
815         public Object run() throws Exception {
816           ACCESS_CONTROLLER.preMerge(ObserverContext.createAndPrepare(RSCP_ENV, null),
817             regions.get(0), regions.get(1));
818           return null;
819         }
820       };
821 
822       verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
823       verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
824         USER_GROUP_WRITE, USER_GROUP_CREATE);
825     } finally {
826       deleteTable(TEST_UTIL, tname);
827     }
828   }
829 
830   @Test (timeout=180000)
831   public void testFlush() throws Exception {
832     AccessTestAction action = new AccessTestAction() {
833       @Override
834       public Object run() throws Exception {
835         ACCESS_CONTROLLER.preFlush(ObserverContext.createAndPrepare(RCP_ENV, null));
836         return null;
837       }
838     };
839 
840     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_GROUP_CREATE,
841       USER_GROUP_ADMIN);
842     verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
843   }
844 
845   @Test (timeout=180000)
846   public void testCompact() throws Exception {
847     AccessTestAction action = new AccessTestAction() {
848       @Override
849       public Object run() throws Exception {
850         ACCESS_CONTROLLER.preCompact(ObserverContext.createAndPrepare(RCP_ENV, null), null, null,
851           ScanType.COMPACT_RETAIN_DELETES);
852         return null;
853       }
854     };
855 
856     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_GROUP_CREATE,
857       USER_GROUP_ADMIN);
858     verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE);
859   }
860 
861   private void verifyRead(AccessTestAction action) throws Exception {
862     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
863       USER_GROUP_READ);
864     verifyDenied(action, USER_NONE, USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_WRITE);
865   }
866 
867   private void verifyReadWrite(AccessTestAction action) throws Exception {
868     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW);
869     verifyDenied(action, USER_NONE, USER_RO, USER_GROUP_ADMIN, USER_GROUP_CREATE, USER_GROUP_READ,
870       USER_GROUP_WRITE);
871   }
872 
873   @Test (timeout=180000)
874   public void testRead() throws Exception {
875     // get action
876     AccessTestAction getAction = new AccessTestAction() {
877       @Override
878       public Object run() throws Exception {
879         Get g = new Get(TEST_ROW);
880         g.addFamily(TEST_FAMILY);
881         try(Connection conn = ConnectionFactory.createConnection(conf);
882             Table t = conn.getTable(TEST_TABLE)) {
883           t.get(g);
884         }
885         return null;
886       }
887     };
888     verifyRead(getAction);
889 
890     // action for scanning
891     AccessTestAction scanAction = new AccessTestAction() {
892       @Override
893       public Object run() throws Exception {
894         Scan s = new Scan();
895         s.addFamily(TEST_FAMILY);
896 
897         try(Connection conn = ConnectionFactory.createConnection(conf);
898             Table table = conn.getTable(TEST_TABLE)) {
899           ResultScanner scanner = table.getScanner(s);
900           try {
901             for (Result r = scanner.next(); r != null; r = scanner.next()) {
902               // do nothing
903             }
904           } catch (IOException e) {
905           } finally {
906             scanner.close();
907           }
908         }
909         return null;
910       }
911     };
912     verifyRead(scanAction);
913   }
914 
915   @Test (timeout=180000)
916   // test put, delete, increment
917   public void testWrite() throws Exception {
918     // put action
919     AccessTestAction putAction = new AccessTestAction() {
920       @Override
921       public Object run() throws Exception {
922         Put p = new Put(TEST_ROW);
923         p.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1));
924         try(Connection conn = ConnectionFactory.createConnection(conf);
925             Table t = conn.getTable(TEST_TABLE)) {
926           t.put(p);
927         }
928         return null;
929       }
930     };
931     verifyWrite(putAction);
932 
933     // delete action
934     AccessTestAction deleteAction = new AccessTestAction() {
935       @Override
936       public Object run() throws Exception {
937         Delete d = new Delete(TEST_ROW);
938         d.deleteFamily(TEST_FAMILY);
939         try(Connection conn = ConnectionFactory.createConnection(conf);
940             Table t = conn.getTable(TEST_TABLE)) {
941           t.delete(d);
942         }
943         return null;
944       }
945     };
946     verifyWrite(deleteAction);
947 
948     // increment action
949     AccessTestAction incrementAction = new AccessTestAction() {
950       @Override
951       public Object run() throws Exception {
952         Increment inc = new Increment(TEST_ROW);
953         inc.addColumn(TEST_FAMILY, TEST_QUALIFIER, 1);
954         try(Connection conn = ConnectionFactory.createConnection(conf);
955             Table t = conn.getTable(TEST_TABLE);) {
956           t.increment(inc);
957         }
958         return null;
959       }
960     };
961     verifyWrite(incrementAction);
962   }
963 
964   @Test (timeout=180000)
965   public void testReadWrite() throws Exception {
966     // action for checkAndDelete
967     AccessTestAction checkAndDeleteAction = new AccessTestAction() {
968       @Override
969       public Object run() throws Exception {
970         Delete d = new Delete(TEST_ROW);
971         d.deleteFamily(TEST_FAMILY);
972         try(Connection conn = ConnectionFactory.createConnection(conf);
973             Table t = conn.getTable(TEST_TABLE);) {
974           t.checkAndDelete(TEST_ROW, TEST_FAMILY, TEST_QUALIFIER,
975               Bytes.toBytes("test_value"), d);
976         }
977         return null;
978       }
979     };
980     verifyReadWrite(checkAndDeleteAction);
981 
982     // action for checkAndPut()
983     AccessTestAction checkAndPut = new AccessTestAction() {
984       @Override
985       public Object run() throws Exception {
986         Put p = new Put(TEST_ROW);
987         p.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1));
988         try(Connection conn = ConnectionFactory.createConnection(conf);
989             Table t = conn.getTable(TEST_TABLE);) {
990           t.checkAndPut(TEST_ROW, TEST_FAMILY, TEST_QUALIFIER,
991               Bytes.toBytes("test_value"), p);
992         }
993         return null;
994       }
995     };
996     verifyReadWrite(checkAndPut);
997   }
998 
999   @Test (timeout=180000)
1000   public void testBulkLoad() throws Exception {
1001     try {
1002       FileSystem fs = TEST_UTIL.getTestFileSystem();
1003       final Path dir = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoad");
1004       fs.mkdirs(dir);
1005       // need to make it globally writable
1006       // so users creating HFiles have write permissions
1007       fs.setPermission(dir, FsPermission.valueOf("-rwxrwxrwx"));
1008 
1009       AccessTestAction bulkLoadAction = new AccessTestAction() {
1010         @Override
1011         public Object run() throws Exception {
1012           int numRows = 3;
1013 
1014           // Making the assumption that the test table won't split between the range
1015           byte[][][] hfileRanges = { { { (byte) 0 }, { (byte) 9 } } };
1016 
1017           Path bulkLoadBasePath = new Path(dir, new Path(User.getCurrent().getName()));
1018           new BulkLoadHelper(bulkLoadBasePath).bulkLoadHFile(TEST_TABLE, TEST_FAMILY,
1019             TEST_QUALIFIER, hfileRanges, numRows);
1020 
1021           return null;
1022         }
1023       };
1024 
1025       // User performing bulk loads must have privilege to read table metadata
1026       // (ADMIN or CREATE)
1027       verifyAllowed(bulkLoadAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
1028         USER_GROUP_CREATE);
1029       verifyDenied(bulkLoadAction, USER_RW, USER_NONE, USER_RO, USER_GROUP_READ, USER_GROUP_WRITE,
1030         USER_GROUP_ADMIN);
1031     } finally {
1032       // Reinit after the bulk upload
1033       TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE);
1034       TEST_UTIL.getHBaseAdmin().enableTable(TEST_TABLE);
1035     }
1036   }
1037 
1038   public class BulkLoadHelper {
1039     private final FileSystem fs;
1040     private final Path loadPath;
1041     private final Configuration conf;
1042 
1043     public BulkLoadHelper(Path loadPath) throws IOException {
1044       fs = TEST_UTIL.getTestFileSystem();
1045       conf = TEST_UTIL.getConfiguration();
1046       loadPath = loadPath.makeQualified(fs);
1047       this.loadPath = loadPath;
1048     }
1049 
1050     private void createHFile(Path path,
1051         byte[] family, byte[] qualifier,
1052         byte[] startKey, byte[] endKey, int numRows) throws IOException {
1053 
1054       HFile.Writer writer = null;
1055       long now = System.currentTimeMillis();
1056       try {
1057         HFileContext context = new HFileContextBuilder().build();
1058         writer = HFile.getWriterFactory(conf, new CacheConfig(conf))
1059             .withPath(fs, path)
1060             .withFileContext(context)
1061             .create();
1062         // subtract 2 since numRows doesn't include boundary keys
1063         for (byte[] key : Bytes.iterateOnSplits(startKey, endKey, true, numRows-2)) {
1064           KeyValue kv = new KeyValue(key, family, qualifier, now, key);
1065           writer.append(kv);
1066         }
1067       } finally {
1068         if(writer != null)
1069           writer.close();
1070       }
1071     }
1072 
1073     private void bulkLoadHFile(
1074         TableName tableName,
1075         byte[] family,
1076         byte[] qualifier,
1077         byte[][][] hfileRanges,
1078         int numRowsPerRange) throws Exception {
1079 
1080       Path familyDir = new Path(loadPath, Bytes.toString(family));
1081       fs.mkdirs(familyDir);
1082       int hfileIdx = 0;
1083       for (byte[][] range : hfileRanges) {
1084         byte[] from = range[0];
1085         byte[] to = range[1];
1086         createHFile(new Path(familyDir, "hfile_"+(hfileIdx++)),
1087             family, qualifier, from, to, numRowsPerRange);
1088       }
1089       //set global read so RegionServer can move it
1090       setPermission(loadPath, FsPermission.valueOf("-rwxrwxrwx"));
1091 
1092       try (Connection conn = ConnectionFactory.createConnection(conf);
1093            HTable table = (HTable)conn.getTable(tableName)) {
1094         TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
1095         LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);
1096         loader.doBulkLoad(loadPath, table);
1097       }
1098     }
1099 
1100     public void setPermission(Path dir, FsPermission perm) throws IOException {
1101       if(!fs.getFileStatus(dir).isDirectory()) {
1102         fs.setPermission(dir,perm);
1103       }
1104       else {
1105         for(FileStatus el : fs.listStatus(dir)) {
1106           fs.setPermission(el.getPath(), perm);
1107           setPermission(el.getPath() , perm);
1108         }
1109       }
1110     }
1111   }
1112 
1113   @Test (timeout=180000)
1114   public void testAppend() throws Exception {
1115 
1116     AccessTestAction appendAction = new AccessTestAction() {
1117       @Override
1118       public Object run() throws Exception {
1119         byte[] row = TEST_ROW;
1120         byte[] qualifier = TEST_QUALIFIER;
1121         Put put = new Put(row);
1122         put.add(TEST_FAMILY, qualifier, Bytes.toBytes(1));
1123         Append append = new Append(row);
1124         append.add(TEST_FAMILY, qualifier, Bytes.toBytes(2));
1125         try(Connection conn = ConnectionFactory.createConnection(conf);
1126             Table t = conn.getTable(TEST_TABLE)) {
1127           t.put(put);
1128           t.append(append);
1129         }
1130         return null;
1131       }
1132     };
1133 
1134     verifyAllowed(appendAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
1135       USER_GROUP_WRITE);
1136     verifyDenied(appendAction, USER_RO, USER_NONE, USER_GROUP_CREATE, USER_GROUP_READ,
1137       USER_GROUP_ADMIN);
1138   }
1139 
1140   @Test (timeout=180000)
1141   public void testGrantRevoke() throws Exception {
1142     AccessTestAction grantAction = new AccessTestAction() {
1143       @Override
1144       public Object run() throws Exception {
1145         try(Connection conn = ConnectionFactory.createConnection(conf);
1146             Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
1147           BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName());
1148           AccessControlService.BlockingInterface protocol =
1149             AccessControlService.newBlockingStub(service);
1150           ProtobufUtil.grant(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null,
1151             Action.READ);
1152         }
1153         return null;
1154       }
1155     };
1156 
1157     AccessTestAction revokeAction = new AccessTestAction() {
1158       @Override
1159       public Object run() throws Exception {
1160         try(Connection conn = ConnectionFactory.createConnection(conf);
1161             Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
1162           BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName());
1163           AccessControlService.BlockingInterface protocol =
1164             AccessControlService.newBlockingStub(service);
1165           ProtobufUtil.revoke(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null,
1166             Action.READ);
1167         }
1168         return null;
1169       }
1170     };
1171 
1172     AccessTestAction getTablePermissionsAction = new AccessTestAction() {
1173       @Override
1174       public Object run() throws Exception {
1175         try(Connection conn = ConnectionFactory.createConnection(conf);
1176             Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)){
1177           BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName());
1178           AccessControlService.BlockingInterface protocol =
1179               AccessControlService.newBlockingStub(service);
1180           ProtobufUtil.getUserPermissions(null, protocol, TEST_TABLE);
1181         }
1182         return null;
1183       }
1184     };
1185 
1186     AccessTestAction getGlobalPermissionsAction = new AccessTestAction() {
1187       @Override
1188       public Object run() throws Exception {
1189         try(Connection conn = ConnectionFactory.createConnection(conf);
1190             Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
1191           BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
1192           AccessControlService.BlockingInterface protocol =
1193             AccessControlService.newBlockingStub(service);
1194           ProtobufUtil.getUserPermissions(null, protocol);
1195         }
1196         return null;
1197       }
1198     };
1199 
1200     verifyAllowed(grantAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
1201     verifyDenied(grantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
1202       USER_GROUP_WRITE, USER_GROUP_CREATE);
1203     try {
1204       verifyAllowed(revokeAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
1205       verifyDenied(revokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
1206         USER_GROUP_WRITE, USER_GROUP_CREATE);
1207 
1208       verifyAllowed(getTablePermissionsAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
1209       verifyDenied(getTablePermissionsAction, USER_CREATE, USER_RW, USER_RO, USER_NONE,
1210         USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
1211 
1212       verifyAllowed(getGlobalPermissionsAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
1213       verifyDenied(getGlobalPermissionsAction, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
1214         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
1215     } finally {
1216       // Cleanup, Grant the revoked permission back to the user
1217       grantOnTable(TEST_UTIL, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null,
1218           Permission.Action.READ);
1219     }
1220   }
1221 
1222   @Test (timeout=180000)
1223   public void testPostGrantRevoke() throws Exception {
1224     final TableName tableName =
1225         TableName.valueOf("TempTable");
1226     final byte[] family1 = Bytes.toBytes("f1");
1227     final byte[] family2 = Bytes.toBytes("f2");
1228     final byte[] qualifier = Bytes.toBytes("q");
1229 
1230     // create table
1231     Admin admin = TEST_UTIL.getHBaseAdmin();
1232     if (admin.tableExists(tableName)) {
1233       deleteTable(TEST_UTIL, tableName);
1234     }
1235     HTableDescriptor htd = new HTableDescriptor(tableName);
1236     htd.addFamily(new HColumnDescriptor(family1));
1237     htd.addFamily(new HColumnDescriptor(family2));
1238     createTable(TEST_UTIL, htd);
1239     try {
1240       // create temp users
1241       User tblUser =
1242           User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser", new String[0]);
1243       User gblUser =
1244           User.createUserForTesting(TEST_UTIL.getConfiguration(), "gbluser", new String[0]);
1245 
1246       // prepare actions:
1247       AccessTestAction putActionAll = new AccessTestAction() {
1248         @Override
1249         public Object run() throws Exception {
1250           Put p = new Put(Bytes.toBytes("a"));
1251           p.add(family1, qualifier, Bytes.toBytes("v1"));
1252           p.add(family2, qualifier, Bytes.toBytes("v2"));
1253           try (Connection conn = ConnectionFactory.createConnection(conf);
1254               Table t = conn.getTable(tableName);) {
1255             t.put(p);
1256           }
1257           return null;
1258         }
1259       };
1260 
1261       AccessTestAction putAction1 = new AccessTestAction() {
1262         @Override
1263         public Object run() throws Exception {
1264           Put p = new Put(Bytes.toBytes("a"));
1265           p.add(family1, qualifier, Bytes.toBytes("v1"));
1266 
1267           try (Connection conn = ConnectionFactory.createConnection(conf);
1268               Table t = conn.getTable(tableName)) {
1269             t.put(p);
1270           }
1271           return null;
1272         }
1273       };
1274 
1275       AccessTestAction putAction2 = new AccessTestAction() {
1276         @Override
1277         public Object run() throws Exception {
1278           Put p = new Put(Bytes.toBytes("a"));
1279           p.add(family2, qualifier, Bytes.toBytes("v2"));
1280           try (Connection conn = ConnectionFactory.createConnection(conf);
1281               Table t = conn.getTable(tableName);) {
1282             t.put(p);
1283           }
1284           return null;
1285         }
1286       };
1287 
1288       AccessTestAction getActionAll = new AccessTestAction() {
1289         @Override
1290         public Object run() throws Exception {
1291           Get g = new Get(TEST_ROW);
1292           g.addFamily(family1);
1293           g.addFamily(family2);
1294           try (Connection conn = ConnectionFactory.createConnection(conf);
1295               Table t = conn.getTable(tableName);) {
1296             t.get(g);
1297           }
1298           return null;
1299         }
1300       };
1301 
1302       AccessTestAction getAction1 = new AccessTestAction() {
1303         @Override
1304         public Object run() throws Exception {
1305           Get g = new Get(TEST_ROW);
1306           g.addFamily(family1);
1307           try (Connection conn = ConnectionFactory.createConnection(conf);
1308               Table t = conn.getTable(tableName)) {
1309             t.get(g);
1310           }
1311           return null;
1312         }
1313       };
1314 
1315       AccessTestAction getAction2 = new AccessTestAction() {
1316         @Override
1317         public Object run() throws Exception {
1318           Get g = new Get(TEST_ROW);
1319           g.addFamily(family2);
1320           try (Connection conn = ConnectionFactory.createConnection(conf);
1321               Table t = conn.getTable(tableName)) {
1322             t.get(g);
1323           }
1324           return null;
1325         }
1326       };
1327 
1328       AccessTestAction deleteActionAll = new AccessTestAction() {
1329         @Override
1330         public Object run() throws Exception {
1331           Delete d = new Delete(TEST_ROW);
1332           d.deleteFamily(family1);
1333           d.deleteFamily(family2);
1334           try (Connection conn = ConnectionFactory.createConnection(conf);
1335               Table t = conn.getTable(tableName)) {
1336             t.delete(d);
1337           }
1338           return null;
1339         }
1340       };
1341 
1342       AccessTestAction deleteAction1 = new AccessTestAction() {
1343         @Override
1344         public Object run() throws Exception {
1345           Delete d = new Delete(TEST_ROW);
1346           d.deleteFamily(family1);
1347           try (Connection conn = ConnectionFactory.createConnection(conf);
1348               Table t = conn.getTable(tableName)) {
1349             t.delete(d);
1350           }
1351           return null;
1352         }
1353       };
1354 
1355       AccessTestAction deleteAction2 = new AccessTestAction() {
1356         @Override
1357         public Object run() throws Exception {
1358           Delete d = new Delete(TEST_ROW);
1359           d.deleteFamily(family2);
1360           try (Connection conn = ConnectionFactory.createConnection(conf);
1361               Table t = conn.getTable(tableName)) {
1362             t.delete(d);
1363           }
1364           return null;
1365         }
1366       };
1367 
1368       // initial check:
1369       verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1370       verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1371       verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1372 
1373       verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1374       verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1375       verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1376 
1377       // grant table read permission
1378       grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.READ);
1379       grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null, Permission.Action.READ);
1380 
1381       // check
1382       verifyAllowed(tblUser, getActionAll, getAction1, getAction2);
1383       verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1384       verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1385 
1386       verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1387       verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1388       verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1389 
1390       // grant table write permission while revoking read permissions
1391       grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.WRITE);
1392       grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null,
1393         Permission.Action.WRITE);
1394 
1395       verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1396       verifyAllowed(tblUser, putActionAll, putAction1, putAction2);
1397       verifyAllowed(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1398 
1399       verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1400       verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1401       verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1402 
1403       // revoke table permissions
1404       revokeGlobal(TEST_UTIL, gblUser.getShortName());
1405       revokeFromTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null);
1406 
1407       verifyDenied(tblUser, getActionAll, getAction1, getAction2);
1408       verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1409       verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1410 
1411       verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1412       verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1413       verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1414 
1415       // grant column family read permission
1416       grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.READ);
1417       grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, family1, null,
1418         Permission.Action.READ);
1419 
1420       // Access should be denied for family2
1421       verifyAllowed(tblUser, getActionAll, getAction1);
1422       verifyDenied(tblUser, getAction2);
1423       verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1424       verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1425 
1426       verifyAllowed(gblUser, getActionAll, getAction1, getAction2);
1427       verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1428       verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1429 
1430       // grant column family write permission
1431       grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.WRITE);
1432       grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, family2, null,
1433         Permission.Action.WRITE);
1434 
1435       // READ from family1, WRITE to family2 are allowed
1436       verifyAllowed(tblUser, getActionAll, getAction1);
1437       verifyAllowed(tblUser, putAction2, deleteAction2);
1438       verifyDenied(tblUser, getAction2);
1439       verifyDenied(tblUser, putActionAll, putAction1);
1440       verifyDenied(tblUser, deleteActionAll, deleteAction1);
1441 
1442       verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1443       verifyAllowed(gblUser, putActionAll, putAction1, putAction2);
1444       verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1445 
1446       // revoke column family permission
1447       revokeGlobal(TEST_UTIL, gblUser.getShortName());
1448       revokeFromTable(TEST_UTIL, tblUser.getShortName(), tableName, family2, null);
1449 
1450       // Revoke on family2 should not have impact on family1 permissions
1451       verifyAllowed(tblUser, getActionAll, getAction1);
1452       verifyDenied(tblUser, getAction2);
1453       verifyDenied(tblUser, putActionAll, putAction1, putAction2);
1454       verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2);
1455 
1456       // Should not have access as global permissions are completely revoked
1457       verifyDenied(gblUser, getActionAll, getAction1, getAction2);
1458       verifyDenied(gblUser, putActionAll, putAction1, putAction2);
1459       verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2);
1460     } finally {
1461       // delete table
1462       deleteTable(TEST_UTIL, tableName);
1463     }
1464   }
1465 
1466   private boolean hasFoundUserPermission(UserPermission userPermission, List<UserPermission> perms) {
1467     return perms.contains(userPermission);
1468   }
1469 
1470   @Test (timeout=180000)
1471   public void testPostGrantRevokeAtQualifierLevel() throws Exception {
1472     final TableName tableName =
1473         TableName.valueOf("testGrantRevokeAtQualifierLevel");
1474     final byte[] family1 = Bytes.toBytes("f1");
1475     final byte[] family2 = Bytes.toBytes("f2");
1476     final byte[] qualifier = Bytes.toBytes("q");
1477 
1478     // create table
1479     Admin admin = TEST_UTIL.getHBaseAdmin();
1480     if (admin.tableExists(tableName)) {
1481       deleteTable(TEST_UTIL, tableName);
1482     }
1483     HTableDescriptor htd = new HTableDescriptor(tableName);
1484     htd.addFamily(new HColumnDescriptor(family1));
1485     htd.addFamily(new HColumnDescriptor(family2));
1486     createTable(TEST_UTIL, htd);
1487 
1488     try {
1489       // create temp users
1490       User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1491 
1492       AccessTestAction getQualifierAction = new AccessTestAction() {
1493         @Override
1494         public Object run() throws Exception {
1495           Get g = new Get(TEST_ROW);
1496           g.addColumn(family1, qualifier);
1497           try (Connection conn = ConnectionFactory.createConnection(conf);
1498               Table t = conn.getTable(tableName)) {
1499             t.get(g);
1500           }
1501           return null;
1502         }
1503       };
1504 
1505       AccessTestAction putQualifierAction = new AccessTestAction() {
1506         @Override
1507         public Object run() throws Exception {
1508           Put p = new Put(TEST_ROW);
1509           p.add(family1, qualifier, Bytes.toBytes("v1"));
1510           try (Connection conn = ConnectionFactory.createConnection(conf);
1511               Table t = conn.getTable(tableName)) {
1512             t.put(p);
1513           }
1514           return null;
1515         }
1516       };
1517 
1518       AccessTestAction deleteQualifierAction = new AccessTestAction() {
1519         @Override
1520         public Object run() throws Exception {
1521           Delete d = new Delete(TEST_ROW);
1522           d.deleteColumn(family1, qualifier);
1523           // d.deleteFamily(family1);
1524           try (Connection conn = ConnectionFactory.createConnection(conf);
1525               Table t = conn.getTable(tableName)) {
1526             t.delete(d);
1527           }
1528           return null;
1529         }
1530       };
1531 
1532       revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, null);
1533 
1534       verifyDenied(user, getQualifierAction);
1535       verifyDenied(user, putQualifierAction);
1536       verifyDenied(user, deleteQualifierAction);
1537 
1538       grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1539         Permission.Action.READ);
1540 
1541       verifyAllowed(user, getQualifierAction);
1542       verifyDenied(user, putQualifierAction);
1543       verifyDenied(user, deleteQualifierAction);
1544 
1545       // only grant write permission
1546       // TODO: comment this portion after HBASE-3583
1547       grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1548         Permission.Action.WRITE);
1549 
1550       verifyDenied(user, getQualifierAction);
1551       verifyAllowed(user, putQualifierAction);
1552       verifyAllowed(user, deleteQualifierAction);
1553 
1554       // grant both read and write permission
1555       grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1556         Permission.Action.READ, Permission.Action.WRITE);
1557 
1558       verifyAllowed(user, getQualifierAction);
1559       verifyAllowed(user, putQualifierAction);
1560       verifyAllowed(user, deleteQualifierAction);
1561 
1562       // revoke family level permission won't impact column level
1563       revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier);
1564 
1565       verifyDenied(user, getQualifierAction);
1566       verifyDenied(user, putQualifierAction);
1567       verifyDenied(user, deleteQualifierAction);
1568     } finally {
1569       // delete table
1570       deleteTable(TEST_UTIL, tableName);
1571     }
1572   }
1573 
1574   @Test (timeout=180000)
1575   public void testPermissionList() throws Exception {
1576     final TableName tableName =
1577         TableName.valueOf("testPermissionList");
1578     final byte[] family1 = Bytes.toBytes("f1");
1579     final byte[] family2 = Bytes.toBytes("f2");
1580     final byte[] qualifier = Bytes.toBytes("q");
1581 
1582     // create table
1583     Admin admin = TEST_UTIL.getHBaseAdmin();
1584     if (admin.tableExists(tableName)) {
1585       deleteTable(TEST_UTIL, tableName);
1586     }
1587     HTableDescriptor htd = new HTableDescriptor(tableName);
1588     htd.addFamily(new HColumnDescriptor(family1));
1589     htd.addFamily(new HColumnDescriptor(family2));
1590     htd.setOwner(USER_OWNER);
1591     createTable(TEST_UTIL, htd);
1592     try {
1593       List<UserPermission> perms;
1594       Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1595       try {
1596         BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1597         AccessControlService.BlockingInterface protocol =
1598             AccessControlService.newBlockingStub(service);
1599         perms = ProtobufUtil.getUserPermissions(null, protocol, tableName);
1600       } finally {
1601         acl.close();
1602       }
1603 
1604       UserPermission ownerperm =
1605           new UserPermission(Bytes.toBytes(USER_OWNER.getName()), tableName, null, Action.values());
1606       assertTrue("Owner should have all permissions on table",
1607         hasFoundUserPermission(ownerperm, perms));
1608 
1609       User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]);
1610       byte[] userName = Bytes.toBytes(user.getShortName());
1611 
1612       UserPermission up =
1613           new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ);
1614       assertFalse("User should not be granted permission: " + up.toString(),
1615         hasFoundUserPermission(up, perms));
1616 
1617       // grant read permission
1618       grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1619         Permission.Action.READ);
1620 
1621       acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1622       try {
1623         BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1624         AccessControlService.BlockingInterface protocol =
1625             AccessControlService.newBlockingStub(service);
1626         perms = ProtobufUtil.getUserPermissions(null, protocol, tableName);
1627       } finally {
1628         acl.close();
1629       }
1630 
1631       UserPermission upToVerify =
1632           new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ);
1633       assertTrue("User should be granted permission: " + upToVerify.toString(),
1634         hasFoundUserPermission(upToVerify, perms));
1635 
1636       upToVerify =
1637           new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE);
1638       assertFalse("User should not be granted permission: " + upToVerify.toString(),
1639         hasFoundUserPermission(upToVerify, perms));
1640 
1641       // grant read+write
1642       grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1643         Permission.Action.WRITE, Permission.Action.READ);
1644 
1645       acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1646       try {
1647         BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1648         AccessControlService.BlockingInterface protocol =
1649             AccessControlService.newBlockingStub(service);
1650         perms = ProtobufUtil.getUserPermissions(null, protocol, tableName);
1651       } finally {
1652         acl.close();
1653       }
1654 
1655       upToVerify =
1656           new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE,
1657               Permission.Action.READ);
1658       assertTrue("User should be granted permission: " + upToVerify.toString(),
1659         hasFoundUserPermission(upToVerify, perms));
1660 
1661       // revoke
1662       revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
1663         Permission.Action.WRITE, Permission.Action.READ);
1664 
1665       acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1666       try {
1667         BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1668         AccessControlService.BlockingInterface protocol =
1669             AccessControlService.newBlockingStub(service);
1670         perms = ProtobufUtil.getUserPermissions(null, protocol, tableName);
1671       } finally {
1672         acl.close();
1673       }
1674 
1675       assertFalse("User should not be granted permission: " + upToVerify.toString(),
1676         hasFoundUserPermission(upToVerify, perms));
1677 
1678       // disable table before modification
1679       admin.disableTable(tableName);
1680 
1681       User newOwner = User.createUserForTesting(conf, "new_owner", new String[] {});
1682       htd.setOwner(newOwner);
1683       admin.modifyTable(tableName, htd);
1684 
1685       acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1686       try {
1687         BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
1688         AccessControlService.BlockingInterface protocol =
1689             AccessControlService.newBlockingStub(service);
1690         perms = ProtobufUtil.getUserPermissions(null, protocol, tableName);
1691       } finally {
1692         acl.close();
1693       }
1694 
1695       UserPermission newOwnerperm =
1696           new UserPermission(Bytes.toBytes(newOwner.getName()), tableName, null, Action.values());
1697       assertTrue("New owner should have all permissions on table",
1698         hasFoundUserPermission(newOwnerperm, perms));
1699     } finally {
1700       // delete table
1701       deleteTable(TEST_UTIL, tableName);
1702     }
1703   }
1704 
1705   @Test (timeout=180000)
1706   public void testGlobalPermissionList() throws Exception {
1707     List<UserPermission> perms;
1708     Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1709     try {
1710       BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
1711       AccessControlService.BlockingInterface protocol =
1712         AccessControlService.newBlockingStub(service);
1713       perms = ProtobufUtil.getUserPermissions(null, protocol);
1714     } finally {
1715       acl.close();
1716     }
1717     UserPermission adminPerm = new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()),
1718       AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"));
1719     assertTrue("Only global users and user admin has permission on table _acl_ per setup",
1720       perms.size() == 5 && hasFoundUserPermission(adminPerm, perms));
1721   }
1722 
1723   /** global operations */
1724   private void verifyGlobal(AccessTestAction action) throws Exception {
1725     verifyAllowed(action, SUPERUSER);
1726 
1727     verifyDenied(action, USER_CREATE, USER_RW, USER_NONE, USER_RO);
1728   }
1729 
1730   @Test (timeout=180000)
1731   public void testCheckPermissions() throws Exception {
1732     // --------------------------------------
1733     // test global permissions
1734     AccessTestAction globalAdmin = new AccessTestAction() {
1735       @Override
1736       public Void run() throws Exception {
1737         checkGlobalPerms(TEST_UTIL, Permission.Action.ADMIN);
1738         return null;
1739       }
1740     };
1741     // verify that only superuser can admin
1742     verifyGlobal(globalAdmin);
1743 
1744     // --------------------------------------
1745     // test multiple permissions
1746     AccessTestAction globalReadWrite = new AccessTestAction() {
1747       @Override
1748       public Void run() throws Exception {
1749         checkGlobalPerms(TEST_UTIL, Permission.Action.READ, Permission.Action.WRITE);
1750         return null;
1751       }
1752     };
1753 
1754     verifyGlobal(globalReadWrite);
1755 
1756     // --------------------------------------
1757     // table/column/qualifier level permissions
1758     final byte[] TEST_Q1 = Bytes.toBytes("q1");
1759     final byte[] TEST_Q2 = Bytes.toBytes("q2");
1760 
1761     User userTable = User.createUserForTesting(conf, "user_check_perms_table", new String[0]);
1762     User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]);
1763     User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]);
1764 
1765     grantOnTable(TEST_UTIL, userTable.getShortName(),
1766       TEST_TABLE, null, null,
1767       Permission.Action.READ);
1768     grantOnTable(TEST_UTIL, userColumn.getShortName(),
1769       TEST_TABLE, TEST_FAMILY, null,
1770       Permission.Action.READ);
1771     grantOnTable(TEST_UTIL, userQualifier.getShortName(),
1772       TEST_TABLE, TEST_FAMILY, TEST_Q1,
1773       Permission.Action.READ);
1774 
1775     try {
1776       AccessTestAction tableRead = new AccessTestAction() {
1777         @Override
1778         public Void run() throws Exception {
1779           checkTablePerms(TEST_UTIL, TEST_TABLE, null, null, Permission.Action.READ);
1780           return null;
1781         }
1782       };
1783 
1784       AccessTestAction columnRead = new AccessTestAction() {
1785         @Override
1786         public Void run() throws Exception {
1787           checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ);
1788           return null;
1789         }
1790       };
1791 
1792       AccessTestAction qualifierRead = new AccessTestAction() {
1793         @Override
1794         public Void run() throws Exception {
1795           checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ);
1796           return null;
1797         }
1798       };
1799 
1800       AccessTestAction multiQualifierRead = new AccessTestAction() {
1801         @Override
1802         public Void run() throws Exception {
1803           checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] {
1804               new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ),
1805               new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q2, Permission.Action.READ), });
1806           return null;
1807         }
1808       };
1809 
1810       AccessTestAction globalAndTableRead = new AccessTestAction() {
1811         @Override
1812         public Void run() throws Exception {
1813           checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] {
1814               new Permission(Permission.Action.READ),
1815               new TablePermission(TEST_TABLE, null, (byte[]) null, Permission.Action.READ), });
1816           return null;
1817         }
1818       };
1819 
1820       AccessTestAction noCheck = new AccessTestAction() {
1821         @Override
1822         public Void run() throws Exception {
1823           checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[0]);
1824           return null;
1825         }
1826       };
1827 
1828       verifyAllowed(tableRead, SUPERUSER, userTable);
1829       verifyDenied(tableRead, userColumn, userQualifier);
1830 
1831       verifyAllowed(columnRead, SUPERUSER, userTable, userColumn);
1832       verifyDenied(columnRead, userQualifier);
1833 
1834       verifyAllowed(qualifierRead, SUPERUSER, userTable, userColumn, userQualifier);
1835 
1836       verifyAllowed(multiQualifierRead, SUPERUSER, userTable, userColumn);
1837       verifyDenied(multiQualifierRead, userQualifier);
1838 
1839       verifyAllowed(globalAndTableRead, SUPERUSER);
1840       verifyDenied(globalAndTableRead, userTable, userColumn, userQualifier);
1841 
1842       verifyAllowed(noCheck, SUPERUSER, userTable, userColumn, userQualifier);
1843 
1844       // --------------------------------------
1845       // test family level multiple permissions
1846       AccessTestAction familyReadWrite = new AccessTestAction() {
1847         @Override
1848         public Void run() throws Exception {
1849           checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ,
1850             Permission.Action.WRITE);
1851           return null;
1852         }
1853       };
1854 
1855       verifyAllowed(familyReadWrite, SUPERUSER, USER_OWNER, USER_CREATE, USER_RW);
1856       verifyDenied(familyReadWrite, USER_NONE, USER_RO);
1857 
1858       // --------------------------------------
1859       // check for wrong table region
1860       CheckPermissionsRequest checkRequest =
1861           CheckPermissionsRequest
1862               .newBuilder()
1863               .addPermission(
1864                 AccessControlProtos.Permission
1865                     .newBuilder()
1866                     .setType(AccessControlProtos.Permission.Type.Table)
1867                     .setTablePermission(
1868                       AccessControlProtos.TablePermission.newBuilder()
1869                           .setTableName(ProtobufUtil.toProtoTableName(TEST_TABLE))
1870                           .addAction(AccessControlProtos.Permission.Action.CREATE))).build();
1871       Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
1872       try {
1873         BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
1874         AccessControlService.BlockingInterface protocol =
1875             AccessControlService.newBlockingStub(channel);
1876         try {
1877           // but ask for TablePermissions for TEST_TABLE
1878           protocol.checkPermissions(null, checkRequest);
1879           fail("this should have thrown CoprocessorException");
1880         } catch (ServiceException ex) {
1881           // expected
1882         }
1883       } finally {
1884         acl.close();
1885       }
1886 
1887     } finally {
1888       revokeFromTable(TEST_UTIL, userTable.getShortName(), TEST_TABLE, null, null,
1889         Permission.Action.READ);
1890       revokeFromTable(TEST_UTIL, userColumn.getShortName(), TEST_TABLE, TEST_FAMILY, null,
1891         Permission.Action.READ);
1892       revokeFromTable(TEST_UTIL, userQualifier.getShortName(), TEST_TABLE, TEST_FAMILY, TEST_Q1,
1893         Permission.Action.READ);
1894     }
1895   }
1896 
1897   @Test (timeout=180000)
1898   public void testStopRegionServer() throws Exception {
1899     AccessTestAction action = new AccessTestAction() {
1900       @Override
1901       public Object run() throws Exception {
1902         ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
1903         return null;
1904       }
1905     };
1906 
1907     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
1908     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
1909       USER_GROUP_WRITE, USER_GROUP_CREATE);
1910   }
1911 
1912   @Test (timeout=180000)
1913   public void testRollWALWriterRequest() throws Exception {
1914     AccessTestAction action = new AccessTestAction() {
1915       @Override
1916       public Object run() throws Exception {
1917         ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContext.createAndPrepare(RSCP_ENV, null));
1918         return null;
1919       }
1920     };
1921 
1922     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
1923     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
1924       USER_GROUP_WRITE, USER_GROUP_CREATE);
1925   }
1926 
1927   @Test (timeout=180000)
1928   public void testOpenRegion() throws Exception {
1929     AccessTestAction action = new AccessTestAction() {
1930       @Override
1931       public Object run() throws Exception {
1932         ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
1933         return null;
1934       }
1935     };
1936 
1937     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
1938     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_CREATE,
1939       USER_GROUP_READ, USER_GROUP_WRITE);
1940   }
1941 
1942   @Test (timeout=180000)
1943   public void testCloseRegion() throws Exception {
1944     AccessTestAction action = new AccessTestAction() {
1945       @Override
1946       public Object run() throws Exception {
1947         ACCESS_CONTROLLER.preClose(ObserverContext.createAndPrepare(RCP_ENV, null), false);
1948         return null;
1949       }
1950     };
1951 
1952     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
1953     verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_CREATE,
1954       USER_GROUP_READ, USER_GROUP_WRITE);
1955   }
1956 
1957   @Test (timeout=180000)
1958   public void testSnapshot() throws Exception {
1959     Admin admin = TEST_UTIL.getHBaseAdmin();
1960     final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE);
1961     SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
1962     builder.setName(TEST_TABLE.getNameAsString() + "-snapshot");
1963     builder.setTable(TEST_TABLE.getNameAsString());
1964     final SnapshotDescription snapshot = builder.build();
1965     AccessTestAction snapshotAction = new AccessTestAction() {
1966       @Override
1967       public Object run() throws Exception {
1968         ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1969           snapshot, htd);
1970         return null;
1971       }
1972     };
1973 
1974     AccessTestAction deleteAction = new AccessTestAction() {
1975       @Override
1976       public Object run() throws Exception {
1977         ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1978           snapshot);
1979         return null;
1980       }
1981     };
1982 
1983     AccessTestAction restoreAction = new AccessTestAction() {
1984       @Override
1985       public Object run() throws Exception {
1986         ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1987           snapshot, htd);
1988         return null;
1989       }
1990     };
1991 
1992     AccessTestAction cloneAction = new AccessTestAction() {
1993       @Override
1994       public Object run() throws Exception {
1995         ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
1996           null, null);
1997         return null;
1998       }
1999     };
2000 
2001     verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2002     verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2003       USER_GROUP_WRITE, USER_GROUP_CREATE);
2004 
2005     verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2006     verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2007       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2008 
2009     verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2010     verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2011       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2012 
2013     verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2014     verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2015       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2016   }
2017 
2018   @Test (timeout=180000)
2019   public void testSnapshotWithOwner() throws Exception {
2020     Admin admin = TEST_UTIL.getHBaseAdmin();
2021     final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE);
2022     SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
2023     builder.setName(TEST_TABLE.getNameAsString() + "-snapshot");
2024     builder.setTable(TEST_TABLE.getNameAsString());
2025     builder.setOwner(USER_OWNER.getName());
2026     final SnapshotDescription snapshot = builder.build();
2027     AccessTestAction snapshotAction = new AccessTestAction() {
2028       @Override
2029       public Object run() throws Exception {
2030         ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
2031           snapshot, htd);
2032         return null;
2033       }
2034     };
2035     verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2036     verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2037       USER_GROUP_WRITE, USER_GROUP_CREATE);
2038 
2039     AccessTestAction deleteAction = new AccessTestAction() {
2040       @Override
2041       public Object run() throws Exception {
2042         ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
2043           snapshot);
2044         return null;
2045       }
2046     };
2047     verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2048     verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2049       USER_GROUP_WRITE, USER_GROUP_CREATE);
2050 
2051     AccessTestAction restoreAction = new AccessTestAction() {
2052       @Override
2053       public Object run() throws Exception {
2054         ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
2055           snapshot, htd);
2056         return null;
2057       }
2058     };
2059     verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2060     verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2061       USER_GROUP_WRITE, USER_GROUP_CREATE);
2062 
2063     AccessTestAction cloneAction = new AccessTestAction() {
2064       @Override
2065       public Object run() throws Exception {
2066         ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
2067           null, null);
2068         return null;
2069       }
2070     };
2071     // Clone by snapshot owner is not allowed , because clone operation creates a new table,
2072     // which needs global admin permission.
2073     verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2074     verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2075       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2076   }
2077 
2078   @Test (timeout=180000)
2079   public void testGlobalAuthorizationForNewRegisteredRS() throws Exception {
2080     LOG.debug("Test for global authorization for a new registered RegionServer.");
2081     MiniHBaseCluster hbaseCluster = TEST_UTIL.getHBaseCluster();
2082 
2083     final Admin admin = TEST_UTIL.getHBaseAdmin();
2084     HTableDescriptor htd = new HTableDescriptor(TEST_TABLE2);
2085     htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
2086     createTable(TEST_UTIL, htd);
2087 
2088     // Starting a new RegionServer.
2089     JVMClusterUtil.RegionServerThread newRsThread = hbaseCluster
2090         .startRegionServer();
2091     final HRegionServer newRs = newRsThread.getRegionServer();
2092 
2093     // Move region to the new RegionServer.
2094     List<HRegionLocation> regions;
2095     try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE2)) {
2096       regions = locator.getAllRegionLocations();
2097     }
2098     HRegionLocation location = regions.get(0);
2099     final HRegionInfo hri = location.getRegionInfo();
2100     final ServerName server = location.getServerName();
2101     try (HTable table = (HTable) systemUserConnection.getTable(TEST_TABLE2)) {
2102       AccessTestAction moveAction = new AccessTestAction() {
2103         @Override
2104         public Object run() throws Exception {
2105           admin.move(hri.getEncodedNameAsBytes(),
2106             Bytes.toBytes(newRs.getServerName().getServerName()));
2107           return null;
2108         }
2109       };
2110       SUPERUSER.runAs(moveAction);
2111 
2112       final int RETRIES_LIMIT = 10;
2113       int retries = 0;
2114       while (newRs.getOnlineRegions(TEST_TABLE2).size() < 1 && retries < RETRIES_LIMIT) {
2115         LOG.debug("Waiting for region to be opened. Already retried " + retries
2116             + " times.");
2117         try {
2118           Thread.sleep(1000);
2119         } catch (InterruptedException e) {
2120         }
2121         retries++;
2122         if (retries == RETRIES_LIMIT - 1) {
2123           fail("Retry exhaust for waiting region to be opened.");
2124         }
2125       }
2126       // Verify write permission for user "admin2" who has the global
2127       // permissions.
2128       AccessTestAction putAction = new AccessTestAction() {
2129         @Override
2130         public Object run() throws Exception {
2131           Put put = new Put(Bytes.toBytes("test"));
2132           put.add(TEST_FAMILY, Bytes.toBytes("qual"), Bytes.toBytes("value"));
2133           table.put(put);
2134           return null;
2135         }
2136       };
2137       USER_ADMIN.runAs(putAction);
2138     }
2139   }
2140 
2141   @Test (timeout=180000)
2142   public void testTableDescriptorsEnumeration() throws Exception {
2143     User TABLE_ADMIN = User.createUserForTesting(conf, "UserA", new String[0]);
2144 
2145     // Grant TABLE ADMIN privs
2146     grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(), TEST_TABLE, null, null,
2147       Permission.Action.ADMIN);
2148     try {
2149       AccessTestAction listTablesAction = new AccessTestAction() {
2150         @Override
2151         public Object run() throws Exception {
2152           try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
2153               Admin admin = conn.getAdmin()) {
2154             return Arrays.asList(admin.listTables());
2155           }
2156         }
2157       };
2158 
2159       AccessTestAction getTableDescAction = new AccessTestAction() {
2160         @Override
2161         public Object run() throws Exception {
2162           try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
2163               Admin admin = conn.getAdmin();) {
2164             return admin.getTableDescriptor(TEST_TABLE);
2165           }
2166         }
2167       };
2168 
2169       verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, TABLE_ADMIN,
2170         USER_GROUP_CREATE, USER_GROUP_ADMIN);
2171       verifyIfEmptyList(listTablesAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2172         USER_GROUP_WRITE);
2173 
2174       verifyAllowed(getTableDescAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER,
2175         TABLE_ADMIN, USER_GROUP_CREATE, USER_GROUP_ADMIN);
2176       verifyDenied(getTableDescAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2177         USER_GROUP_WRITE);
2178     } finally {
2179       // Cleanup, revoke TABLE ADMIN privs
2180       revokeFromTable(TEST_UTIL, TABLE_ADMIN.getShortName(), TEST_TABLE, null, null,
2181         Permission.Action.ADMIN);
2182     }
2183   }
2184 
2185   @Test (timeout=180000)
2186   public void testTableNameEnumeration() throws Exception {
2187     AccessTestAction listTablesAction = new AccessTestAction() {
2188       @Override
2189       public Object run() throws Exception {
2190         Connection unmanagedConnection =
2191             ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
2192         Admin admin = unmanagedConnection.getAdmin();
2193         try {
2194           return Arrays.asList(admin.listTableNames());
2195         } finally {
2196           admin.close();
2197           unmanagedConnection.close();
2198         }
2199       }
2200     };
2201 
2202     verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_RW,
2203       USER_RO, USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_WRITE);
2204     verifyIfEmptyList(listTablesAction, USER_NONE);
2205   }
2206 
2207   @Test (timeout=180000)
2208   public void testTableDeletion() throws Exception {
2209     User TABLE_ADMIN = User.createUserForTesting(conf, "TestUser", new String[0]);
2210     final TableName tname = TableName.valueOf("testTableDeletion");
2211     createTestTable(tname);
2212 
2213     // Grant TABLE ADMIN privs
2214     grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(), tname, null, null, Permission.Action.ADMIN);
2215 
2216     AccessTestAction deleteTableAction = new AccessTestAction() {
2217       @Override
2218       public Object run() throws Exception {
2219         Connection unmanagedConnection =
2220             ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
2221         Admin admin = unmanagedConnection.getAdmin();
2222         try {
2223           deleteTable(TEST_UTIL, admin, tname);
2224         } finally {
2225           admin.close();
2226           unmanagedConnection.close();
2227         }
2228         return null;
2229       }
2230     };
2231 
2232     verifyDenied(deleteTableAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ,
2233       USER_GROUP_WRITE);
2234     verifyAllowed(deleteTableAction, TABLE_ADMIN);
2235   }
2236 
2237   private void createTestTable(TableName tname) throws Exception {
2238     HTableDescriptor htd = new HTableDescriptor(tname);
2239     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
2240     hcd.setMaxVersions(100);
2241     htd.addFamily(hcd);
2242     htd.setOwner(USER_OWNER);
2243     createTable(TEST_UTIL, htd, new byte[][]{Bytes.toBytes("s")});
2244   }
2245 
2246   @Test (timeout=180000)
2247   public void testNamespaceUserGrant() throws Exception {
2248     AccessTestAction getAction = new AccessTestAction() {
2249       @Override
2250       public Object run() throws Exception {
2251         try(Connection conn = ConnectionFactory.createConnection(conf);
2252             Table t = conn.getTable(TEST_TABLE);) {
2253           return t.get(new Get(TEST_ROW));
2254         }
2255       }
2256     };
2257 
2258     String namespace = TEST_TABLE.getNamespaceAsString();
2259 
2260     // Grant namespace READ to USER_NONE, this should supersede any table permissions
2261     grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ);
2262     // Now USER_NONE should be able to read
2263     verifyAllowed(getAction, USER_NONE);
2264 
2265     // Revoke namespace READ to USER_NONE
2266     revokeFromNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ);
2267     verifyDenied(getAction, USER_NONE);
2268   }
2269 
2270   @Test (timeout=180000)
2271   public void testAccessControlClientGrantRevoke() throws Exception {
2272     // Create user for testing, who has no READ privileges by default.
2273     User testGrantRevoke = User.createUserForTesting(conf, "testGrantRevoke", new String[0]);
2274     AccessTestAction getAction = new AccessTestAction() {
2275       @Override
2276       public Object run() throws Exception {
2277         try(Connection conn = ConnectionFactory.createConnection(conf);
2278             Table t = conn.getTable(TEST_TABLE);) {
2279           return t.get(new Get(TEST_ROW));
2280         }
2281       }
2282     };
2283 
2284     verifyDenied(getAction, testGrantRevoke);
2285 
2286     // Grant table READ permissions to testGrantRevoke.
2287     try {
2288       grantOnTableUsingAccessControlClient(TEST_UTIL, systemUserConnection,
2289         testGrantRevoke.getShortName(), TEST_TABLE, null, null, Permission.Action.READ);
2290     } catch (Throwable e) {
2291       LOG.error("error during call of AccessControlClient.grant. ", e);
2292     }
2293 
2294     // Now testGrantRevoke should be able to read also
2295     verifyAllowed(getAction, testGrantRevoke);
2296 
2297     // Revoke table READ permission to testGrantRevoke.
2298     try {
2299       revokeFromTableUsingAccessControlClient(TEST_UTIL, systemUserConnection,
2300         testGrantRevoke.getShortName(), TEST_TABLE, null, null, Permission.Action.READ);
2301     } catch (Throwable e) {
2302       LOG.error("error during call of AccessControlClient.revoke ", e);
2303     }
2304 
2305     // Now testGrantRevoke shouldn't be able read
2306     verifyDenied(getAction, testGrantRevoke);
2307   }
2308 
2309   @Test (timeout=180000)
2310   public void testAccessControlClientGlobalGrantRevoke() throws Exception {
2311     // Create user for testing, who has no READ privileges by default.
2312     User testGlobalGrantRevoke = User.createUserForTesting(conf,
2313       "testGlobalGrantRevoke", new String[0]);
2314     AccessTestAction getAction = new AccessTestAction() {
2315       @Override
2316       public Object run() throws Exception {
2317         try(Connection conn = ConnectionFactory.createConnection(conf);
2318             Table t = conn.getTable(TEST_TABLE)) {
2319           return t.get(new Get(TEST_ROW));
2320         }
2321       }
2322     };
2323 
2324     verifyDenied(getAction, testGlobalGrantRevoke);
2325 
2326     // Grant table READ permissions to testGlobalGrantRevoke.
2327     String userName = testGlobalGrantRevoke.getShortName();
2328     try {
2329       grantGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection,
2330           userName, Permission.Action.READ);
2331     } catch (Throwable e) {
2332       LOG.error("error during call of AccessControlClient.grant. ", e);
2333     }
2334     try {
2335       // Now testGlobalGrantRevoke should be able to read also
2336       verifyAllowed(getAction, testGlobalGrantRevoke);
2337 
2338       // Revoke table READ permission to testGlobalGrantRevoke.
2339       try {
2340         revokeGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection,
2341           userName, Permission.Action.READ);
2342       } catch (Throwable e) {
2343         LOG.error("error during call of AccessControlClient.revoke ", e);
2344       }
2345 
2346       // Now testGlobalGrantRevoke shouldn't be able read
2347       verifyDenied(getAction, testGlobalGrantRevoke);
2348     } finally {
2349       revokeGlobal(TEST_UTIL, userName, Permission.Action.READ);
2350     }
2351   }
2352 
2353   @Test (timeout=180000)
2354   public void testAccessControlClientGrantRevokeOnNamespace() throws Exception {
2355     // Create user for testing, who has no READ privileges by default.
2356     User testNS = User.createUserForTesting(conf, "testNS", new String[0]);
2357     AccessTestAction getAction = new AccessTestAction() {
2358       @Override
2359       public Object run() throws Exception {
2360         try(Connection conn = ConnectionFactory.createConnection(conf);
2361             Table t = conn.getTable(TEST_TABLE);) {
2362           return t.get(new Get(TEST_ROW));
2363         }
2364       }
2365     };
2366 
2367     verifyDenied(getAction, testNS);
2368 
2369     String userName = testNS.getShortName();
2370     String namespace = TEST_TABLE.getNamespaceAsString();
2371     // Grant namespace READ to testNS, this should supersede any table permissions
2372     try {
2373       grantOnNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName,
2374         namespace, Permission.Action.READ);
2375     } catch (Throwable e) {
2376       LOG.error("error during call of AccessControlClient.grant. ", e);
2377     }
2378     try {
2379       // Now testNS should be able to read also
2380       verifyAllowed(getAction, testNS);
2381 
2382       // Revoke namespace READ to testNS, this should supersede any table permissions
2383       try {
2384         revokeFromNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName,
2385           namespace, Permission.Action.READ);
2386       } catch (Throwable e) {
2387         LOG.error("error during call of AccessControlClient.revoke ", e);
2388       }
2389 
2390       // Now testNS shouldn't be able read
2391       verifyDenied(getAction, testNS);
2392     } finally {
2393       revokeFromNamespace(TEST_UTIL, userName, namespace, Permission.Action.READ);
2394     }
2395   }
2396 
2397 
2398   public static class PingCoprocessor extends PingService implements Coprocessor,
2399       CoprocessorService {
2400 
2401     @Override
2402     public void start(CoprocessorEnvironment env) throws IOException { }
2403 
2404     @Override
2405     public void stop(CoprocessorEnvironment env) throws IOException { }
2406 
2407     @Override
2408     public Service getService() {
2409       return this;
2410     }
2411 
2412     @Override
2413     public void ping(RpcController controller, PingRequest request,
2414         RpcCallback<PingResponse> callback) {
2415       callback.run(PingResponse.newBuilder().setPong("Pong!").build());
2416     }
2417 
2418     @Override
2419     public void count(RpcController controller, CountRequest request,
2420         RpcCallback<CountResponse> callback) {
2421       callback.run(CountResponse.newBuilder().build());
2422     }
2423 
2424     @Override
2425     public void increment(RpcController controller, IncrementCountRequest requet,
2426         RpcCallback<IncrementCountResponse> callback) {
2427       callback.run(IncrementCountResponse.newBuilder().build());
2428     }
2429 
2430     @Override
2431     public void hello(RpcController controller, HelloRequest request,
2432         RpcCallback<HelloResponse> callback) {
2433       callback.run(HelloResponse.newBuilder().setResponse("Hello!").build());
2434     }
2435 
2436     @Override
2437     public void noop(RpcController controller, NoopRequest request,
2438         RpcCallback<NoopResponse> callback) {
2439       callback.run(NoopResponse.newBuilder().build());
2440     }
2441   }
2442 
2443   @Test (timeout=180000)
2444   public void testCoprocessorExec() throws Exception {
2445     // Set up our ping endpoint service on all regions of our test table
2446     for (JVMClusterUtil.RegionServerThread thread:
2447         TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
2448       HRegionServer rs = thread.getRegionServer();
2449       for (Region region: rs.getOnlineRegions(TEST_TABLE)) {
2450         region.getCoprocessorHost().load(PingCoprocessor.class,
2451           Coprocessor.PRIORITY_USER, conf);
2452       }
2453     }
2454 
2455     // Create users for testing, and grant EXEC privileges on our test table
2456     // only to user A
2457     User userA = User.createUserForTesting(conf, "UserA", new String[0]);
2458     User userB = User.createUserForTesting(conf, "UserB", new String[0]);
2459 
2460     grantOnTable(TEST_UTIL, userA.getShortName(),
2461       TEST_TABLE, null, null,
2462       Permission.Action.EXEC);
2463     try {
2464       // Create an action for invoking our test endpoint
2465       AccessTestAction execEndpointAction = new AccessTestAction() {
2466         @Override
2467         public Object run() throws Exception {
2468           try (Connection conn = ConnectionFactory.createConnection(conf);
2469               Table t = conn.getTable(TEST_TABLE);) {
2470             BlockingRpcChannel service = t.coprocessorService(HConstants.EMPTY_BYTE_ARRAY);
2471             PingCoprocessor.newBlockingStub(service).noop(null, NoopRequest.newBuilder().build());
2472           }
2473           return null;
2474         }
2475       };
2476 
2477       String namespace = TEST_TABLE.getNamespaceAsString();
2478       // Now grant EXEC to the entire namespace to user B
2479       grantOnNamespace(TEST_UTIL, userB.getShortName(), namespace, Permission.Action.EXEC);
2480       // User B should now be allowed also
2481       verifyAllowed(execEndpointAction, userA, userB);
2482 
2483       revokeFromNamespace(TEST_UTIL, userB.getShortName(), namespace, Permission.Action.EXEC);
2484       // Verify that EXEC permission is checked correctly
2485       verifyDenied(execEndpointAction, userB);
2486       verifyAllowed(execEndpointAction, userA);
2487     } finally {
2488       // Cleanup, revoke the userA privileges
2489       revokeFromTable(TEST_UTIL, userA.getShortName(), TEST_TABLE, null, null,
2490         Permission.Action.EXEC);
2491     }
2492   }
2493 
2494   @Test (timeout=180000)
2495   public void testSetQuota() throws Exception {
2496     AccessTestAction setUserQuotaAction = new AccessTestAction() {
2497       @Override
2498       public Object run() throws Exception {
2499         ACCESS_CONTROLLER.preSetUserQuota(ObserverContext.createAndPrepare(CP_ENV, null),
2500           null, null);
2501         return null;
2502       }
2503     };
2504 
2505     AccessTestAction setUserTableQuotaAction = new AccessTestAction() {
2506       @Override
2507       public Object run() throws Exception {
2508         ACCESS_CONTROLLER.preSetUserQuota(ObserverContext.createAndPrepare(CP_ENV, null), null,
2509           TEST_TABLE, null);
2510         return null;
2511       }
2512     };
2513 
2514     AccessTestAction setUserNamespaceQuotaAction = new AccessTestAction() {
2515       @Override
2516       public Object run() throws Exception {
2517         ACCESS_CONTROLLER.preSetUserQuota(ObserverContext.createAndPrepare(CP_ENV, null),
2518           null, (String)null, null);
2519         return null;
2520       }
2521     };
2522 
2523     AccessTestAction setTableQuotaAction = new AccessTestAction() {
2524       @Override
2525       public Object run() throws Exception {
2526         ACCESS_CONTROLLER.preSetTableQuota(ObserverContext.createAndPrepare(CP_ENV, null),
2527           TEST_TABLE, null);
2528         return null;
2529       }
2530     };
2531 
2532     AccessTestAction setNamespaceQuotaAction = new AccessTestAction() {
2533       @Override
2534       public Object run() throws Exception {
2535         ACCESS_CONTROLLER.preSetNamespaceQuota(ObserverContext.createAndPrepare(CP_ENV, null),
2536           null, null);
2537         return null;
2538       }
2539     };
2540 
2541     verifyAllowed(setUserQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2542     verifyDenied(setUserQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2543       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2544 
2545     verifyAllowed(setUserTableQuotaAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2546     verifyDenied(setUserTableQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE,
2547       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2548 
2549     verifyAllowed(setUserNamespaceQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2550     verifyDenied(setUserNamespaceQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2551       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2552 
2553     verifyAllowed(setTableQuotaAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN);
2554     verifyDenied(setTableQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE);
2555 
2556     verifyAllowed(setNamespaceQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
2557     verifyDenied(setNamespaceQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2558       USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
2559   }
2560 
2561   @Test (timeout=180000)
2562   public void testGetNamespacePermission() throws Exception {
2563     String namespace = "testGetNamespacePermission";
2564     NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build();
2565     createNamespace(TEST_UTIL, desc);
2566     grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ);
2567     try {
2568       List<UserPermission> namespacePermissions = AccessControlClient.getUserPermissions(
2569           systemUserConnection, AccessControlLists.toNamespaceEntry(namespace));
2570       assertTrue(namespacePermissions != null);
2571       assertTrue(namespacePermissions.size() == 1);
2572     } catch (Throwable thw) {
2573       throw new HBaseException(thw);
2574     }
2575     deleteNamespace(TEST_UTIL, namespace);
2576   }
2577 
2578   @Test (timeout=180000)
2579   public void testTruncatePerms() throws Exception {
2580     try {
2581       List<UserPermission> existingPerms = AccessControlClient.getUserPermissions(
2582           systemUserConnection, TEST_TABLE.getNameAsString());
2583       assertTrue(existingPerms != null);
2584       assertTrue(existingPerms.size() > 1);
2585       TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE);
2586       TEST_UTIL.truncateTable(TEST_TABLE);
2587       TEST_UTIL.waitTableAvailable(TEST_TABLE);
2588       List<UserPermission> perms = AccessControlClient.getUserPermissions(
2589           systemUserConnection, TEST_TABLE.getNameAsString());
2590       assertTrue(perms != null);
2591       assertEquals(existingPerms.size(), perms.size());
2592     } catch (Throwable e) {
2593       throw new HBaseIOException(e);
2594     }
2595   }
2596 
2597   private PrivilegedAction<List<UserPermission>> getPrivilegedAction(final String regex) {
2598     return new PrivilegedAction<List<UserPermission>>() {
2599       @Override
2600       public List<UserPermission> run() {
2601         try(Connection conn = ConnectionFactory.createConnection(conf);) {
2602           return AccessControlClient.getUserPermissions(conn, regex);
2603         } catch (Throwable e) {
2604           LOG.error("error during call of AccessControlClient.getUserPermissions.", e);
2605           return null;
2606         }
2607       }
2608     };
2609   }
2610 
2611   @Test (timeout=180000)
2612   public void testAccessControlClientUserPerms() throws Exception {
2613     TableName tname = TableName.valueOf("testAccessControlClientUserPerms");
2614     createTestTable(tname);
2615     try {
2616       final String regex = tname.getNameWithNamespaceInclAsString();
2617       User testUserPerms = User.createUserForTesting(conf, "testUserPerms", new String[0]);
2618       assertEquals(0, testUserPerms.runAs(getPrivilegedAction(regex)).size());
2619       // Grant TABLE ADMIN privs to testUserPerms
2620       grantOnTable(TEST_UTIL, testUserPerms.getShortName(), tname, null, null, Action.ADMIN);
2621       List<UserPermission> perms = testUserPerms.runAs(getPrivilegedAction(regex));
2622       assertNotNull(perms);
2623       // Superuser, testUserPerms
2624       assertEquals(2, perms.size());
2625     } finally {
2626       deleteTable(TEST_UTIL, tname);
2627     }
2628   }
2629 
2630   @Test (timeout=180000)
2631   public void testAccessControllerUserPermsRegexHandling() throws Exception {
2632     User testRegexHandler = User.createUserForTesting(conf, "testRegexHandling", new String[0]);
2633 
2634     final String REGEX_ALL_TABLES = ".*";
2635     final String tableName = "testRegex";
2636     final TableName table1 = TableName.valueOf(tableName);
2637     final byte[] family = Bytes.toBytes("f1");
2638 
2639     // create table in default ns
2640     Admin admin = TEST_UTIL.getHBaseAdmin();
2641     HTableDescriptor htd = new HTableDescriptor(table1);
2642     htd.addFamily(new HColumnDescriptor(family));
2643     createTable(TEST_UTIL, htd);
2644 
2645     // creating the ns and table in it
2646     String ns = "testNamespace";
2647     NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build();
2648     final TableName table2 = TableName.valueOf(ns, tableName);
2649     createNamespace(TEST_UTIL, desc);
2650     htd = new HTableDescriptor(table2);
2651     htd.addFamily(new HColumnDescriptor(family));
2652     createTable(TEST_UTIL, htd);
2653 
2654     // Verify that we can read sys-tables
2655     String aclTableName = AccessControlLists.ACL_TABLE_NAME.getNameAsString();
2656     assertEquals(5, SUPERUSER.runAs(getPrivilegedAction(aclTableName)).size());
2657     assertEquals(0, testRegexHandler.runAs(getPrivilegedAction(aclTableName)).size());
2658 
2659     // Grant TABLE ADMIN privs to testUserPerms
2660     assertEquals(0, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size());
2661     grantOnTable(TEST_UTIL, testRegexHandler.getShortName(), table1, null, null, Action.ADMIN);
2662     assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size());
2663     grantOnTable(TEST_UTIL, testRegexHandler.getShortName(), table2, null, null, Action.ADMIN);
2664     assertEquals(4, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size());
2665 
2666     // USER_ADMIN, testUserPerms must have a row each.
2667     assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(tableName)).size());
2668     assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(
2669           NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR + TableName.NAMESPACE_DELIM + tableName)
2670         ).size());
2671     assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(
2672         ns + TableName.NAMESPACE_DELIM + tableName)).size());
2673     assertEquals(0, testRegexHandler.runAs(getPrivilegedAction("notMatchingAny")).size());
2674 
2675     deleteTable(TEST_UTIL, table1);
2676     deleteTable(TEST_UTIL, table2);
2677     deleteNamespace(TEST_UTIL, ns);
2678   }
2679 
2680   private void verifyAnyCreate(AccessTestAction action) throws Exception {
2681     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_ADMIN_CF,
2682       USER_GROUP_CREATE);
2683     verifyDenied(action, USER_NONE, USER_RO, USER_RW, USER_GROUP_READ, USER_GROUP_WRITE,
2684       USER_GROUP_ADMIN);
2685   }
2686 
2687   @Test (timeout=180000)
2688   public void testPrepareAndCleanBulkLoad() throws Exception {
2689     AccessTestAction prepareBulkLoadAction = new AccessTestAction() {
2690       @Override
2691       public Object run() throws Exception {
2692         ACCESS_CONTROLLER.prePrepareBulkLoad(ObserverContext.createAndPrepare(RCP_ENV, null),
2693           null);
2694         return null;
2695       }
2696     };
2697     AccessTestAction cleanupBulkLoadAction = new AccessTestAction() {
2698       @Override
2699       public Object run() throws Exception {
2700         ACCESS_CONTROLLER.preCleanupBulkLoad(ObserverContext.createAndPrepare(RCP_ENV, null),
2701           null);
2702         return null;
2703       }
2704     };
2705     verifyAnyCreate(prepareBulkLoadAction);
2706     verifyAnyCreate(cleanupBulkLoadAction);
2707   }
2708 
2709   @Test (timeout=180000)
2710   public void testReplicateLogEntries() throws Exception {
2711     AccessTestAction replicateLogEntriesAction = new AccessTestAction() {
2712       @Override
2713       public Object run() throws Exception {
2714         ACCESS_CONTROLLER.preReplicateLogEntries(ObserverContext.createAndPrepare(RSCP_ENV, null),
2715           null, null);
2716         ACCESS_CONTROLLER.postReplicateLogEntries(ObserverContext.createAndPrepare(RSCP_ENV, null),
2717           null, null);
2718         return null;
2719       }
2720     };
2721 
2722     verifyAllowed(replicateLogEntriesAction, SUPERUSER, USER_ADMIN, USER_GROUP_WRITE);
2723     verifyDenied(replicateLogEntriesAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER,
2724       USER_GROUP_READ, USER_GROUP_ADMIN, USER_GROUP_CREATE);
2725   }
2726 }