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