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  package org.apache.hadoop.hbase.security.access;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.mockito.Mockito.mock;
22  import static org.mockito.Mockito.when;
23  import com.google.common.collect.Lists;
24  import java.util.List;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.Cell;
29  import org.apache.hadoop.hbase.Coprocessor;
30  import org.apache.hadoop.hbase.HBaseTestingUtility;
31  import org.apache.hadoop.hbase.HColumnDescriptor;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.HRegionInfo;
34  import org.apache.hadoop.hbase.HTableDescriptor;
35  import org.apache.hadoop.hbase.NamespaceDescriptor;
36  import org.apache.hadoop.hbase.ServerName;
37  import org.apache.hadoop.hbase.TableName;
38  import org.apache.hadoop.hbase.TableNameTestRule;
39  import org.apache.hadoop.hbase.TableNotFoundException;
40  import org.apache.hadoop.hbase.client.Admin;
41  import org.apache.hadoop.hbase.client.Append;
42  import org.apache.hadoop.hbase.client.Connection;
43  import org.apache.hadoop.hbase.client.ConnectionFactory;
44  import org.apache.hadoop.hbase.client.Delete;
45  import org.apache.hadoop.hbase.client.Durability;
46  import org.apache.hadoop.hbase.client.Get;
47  import org.apache.hadoop.hbase.client.Increment;
48  import org.apache.hadoop.hbase.client.Mutation;
49  import org.apache.hadoop.hbase.client.Put;
50  import org.apache.hadoop.hbase.client.Result;
51  import org.apache.hadoop.hbase.client.ResultScanner;
52  import org.apache.hadoop.hbase.client.Scan;
53  import org.apache.hadoop.hbase.client.Table;
54  import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
55  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
56  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
57  import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
58  import org.apache.hadoop.hbase.filter.BinaryComparator;
59  import org.apache.hadoop.hbase.filter.CompareFilter;
60  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
61  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
62  import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
63  import org.apache.hadoop.hbase.regionserver.Region;
64  import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
65  import org.apache.hadoop.hbase.regionserver.RegionScanner;
66  import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
67  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
68  import org.apache.hadoop.hbase.security.User;
69  import org.apache.hadoop.hbase.security.access.Permission.Action;
70  import org.apache.hadoop.hbase.testclassification.LargeTests;
71  import org.apache.hadoop.hbase.util.Bytes;
72  import org.apache.hadoop.hbase.util.Pair;
73  import org.apache.log4j.Level;
74  import org.apache.log4j.Logger;
75  import org.junit.After;
76  import org.junit.AfterClass;
77  import org.junit.Before;
78  import org.junit.BeforeClass;
79  import org.junit.Rule;
80  import org.junit.Test;
81  import org.junit.experimental.categories.Category;
82  
83  @Category(LargeTests.class)
84  public class TestWithDisabledAuthorization extends SecureTestUtil {
85    private static final Log LOG = LogFactory.getLog(TestWithDisabledAuthorization.class);
86  
87    static {
88      Logger.getLogger(AccessController.class).setLevel(Level.TRACE);
89      Logger.getLogger(AccessControlFilter.class).setLevel(Level.TRACE);
90      Logger.getLogger(TableAuthManager.class).setLevel(Level.TRACE);
91    }
92  
93    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
94  
95    private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
96    private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
97    private static final byte[] TEST_ROW = Bytes.toBytes("testrow");
98    private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
99    private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
100   private static final byte[] TEST_Q3 = Bytes.toBytes("q3");
101   private static final byte[] TEST_Q4 = Bytes.toBytes("q4");
102   private static final byte[] ZERO = Bytes.toBytes(0L);
103 
104   private static MasterCoprocessorEnvironment CP_ENV;
105   private static AccessController ACCESS_CONTROLLER;
106   private static RegionServerCoprocessorEnvironment RSCP_ENV;
107   private RegionCoprocessorEnvironment RCP_ENV;
108 
109   @Rule public TableNameTestRule testTable = new TableNameTestRule();
110 
111   // default users
112   
113   // superuser
114   private static User SUPERUSER;
115   // user granted with all global permission
116   private static User USER_ADMIN;
117   // user with rw permissions on column family.
118   private static User USER_RW;
119   // user with read-only permissions
120   private static User USER_RO;
121   // user is table owner. will have all permissions on table
122   private static User USER_OWNER;
123   // user with create table permissions alone
124   private static User USER_CREATE;
125   // user with no permissions
126   private static User USER_NONE;
127   // user with only partial read-write perms (on family:q1 only)
128   private static User USER_QUAL;
129 
130   @BeforeClass
131   public static void setupBeforeClass() throws Exception {
132     Configuration conf = TEST_UTIL.getConfiguration();
133     // Up the handlers; this test needs more than usual.
134     TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
135     // Enable security
136     enableSecurity(conf);
137     // We expect 0.98 cell ACL semantics
138     conf.setBoolean(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, false);
139     // Enable EXEC permission checking
140     conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true);
141     // Verify enableSecurity sets up what we require
142     verifyConfiguration(conf);
143 
144     // Now, DISABLE only active authorization
145     conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
146 
147     // Start the minicluster
148     TEST_UTIL.startMiniCluster();
149     MasterCoprocessorHost cpHost =
150         TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
151     cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
152     ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
153     CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
154       Coprocessor.PRIORITY_HIGHEST, 1, conf);
155     RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
156       .getRegionServerCoprocessorHost();
157     RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
158       Coprocessor.PRIORITY_HIGHEST, 1, conf);
159 
160     // Wait for the ACL table to become available
161     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
162 
163     // create a set of test users
164     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
165     USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]);
166     USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
167     USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]);
168     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
169     USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
170     USER_QUAL = User.createUserForTesting(conf, "rwpartial", new String[0]);
171     USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]);
172   }
173 
174   @AfterClass
175   public static void tearDownAfterClass() throws Exception {
176     TEST_UTIL.shutdownMiniCluster();
177   }
178 
179   @Before
180   public void setUp() throws Exception {
181     // Create the test table (owner added to the _acl_ table)
182     Admin admin = TEST_UTIL.getHBaseAdmin();
183     HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
184     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
185     hcd.setMaxVersions(100);
186     htd.addFamily(hcd);
187     htd.setOwner(USER_OWNER);
188     admin.createTable(htd, new byte[][] { Bytes.toBytes("s") });
189     TEST_UTIL.waitUntilAllRegionsAssigned(testTable.getTableName());
190 
191     Region region = TEST_UTIL.getHBaseCluster().getRegions(testTable.getTableName()).get(0);
192     RegionCoprocessorHost rcpHost = region.getCoprocessorHost();
193     RCP_ENV = rcpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
194       Coprocessor.PRIORITY_HIGHEST, 1, TEST_UTIL.getConfiguration());
195 
196     // Set up initial grants
197 
198     grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(),
199       Permission.Action.ADMIN,
200       Permission.Action.CREATE,
201       Permission.Action.READ,
202       Permission.Action.WRITE);
203 
204     grantOnTable(TEST_UTIL, USER_RW.getShortName(),
205       testTable.getTableName(), TEST_FAMILY, null,
206       Permission.Action.READ,
207       Permission.Action.WRITE);
208 
209     // USER_CREATE is USER_RW plus CREATE permissions
210     grantOnTable(TEST_UTIL, USER_CREATE.getShortName(),
211       testTable.getTableName(), null, null,
212       Permission.Action.CREATE,
213       Permission.Action.READ,
214       Permission.Action.WRITE);
215 
216     grantOnTable(TEST_UTIL, USER_RO.getShortName(),
217       testTable.getTableName(), TEST_FAMILY, null,
218       Permission.Action.READ);
219 
220     grantOnTable(TEST_UTIL, USER_QUAL.getShortName(),
221       testTable.getTableName(), TEST_FAMILY, TEST_Q1,
222       Permission.Action.READ,
223       Permission.Action.WRITE);
224 
225     assertEquals(5, AccessControlLists.getTablePermissions(TEST_UTIL.getConfiguration(),
226       testTable.getTableName()).size());
227   }
228 
229   @After
230   public void tearDown() throws Exception {
231     // Clean the _acl_ table
232     try {
233       deleteTable(TEST_UTIL, testTable.getTableName());
234     } catch (TableNotFoundException ex) {
235       // Test deleted the table, no problem
236       LOG.info("Test deleted table " + testTable.getTableName());
237     }
238     // Verify all table/namespace permissions are erased
239     assertEquals(0, AccessControlLists.getTablePermissions(TEST_UTIL.getConfiguration(),
240       testTable.getTableName()).size());
241     assertEquals(0, AccessControlLists.getNamespacePermissions(TEST_UTIL.getConfiguration(),
242       testTable.getTableName().getNamespaceAsString()).size());
243   }
244 
245   @Test
246   public void testCheckPermissions() throws Exception {
247 
248     AccessTestAction checkGlobalAdmin = new AccessTestAction() {
249       @Override
250       public Void run() throws Exception {
251         checkGlobalPerms(TEST_UTIL, Permission.Action.ADMIN);
252         return null;
253       }
254     };
255 
256     verifyAllowed(checkGlobalAdmin, SUPERUSER, USER_ADMIN);
257     verifyDenied(checkGlobalAdmin, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
258       USER_NONE);
259 
260     AccessTestAction checkGlobalRead = new AccessTestAction() {
261       @Override
262       public Void run() throws Exception {
263         checkGlobalPerms(TEST_UTIL, Permission.Action.READ);
264         return null;
265       }
266     };
267 
268     verifyAllowed(checkGlobalRead, SUPERUSER, USER_ADMIN);
269     verifyDenied(checkGlobalRead, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
270       USER_NONE);
271 
272     AccessTestAction checkGlobalReadWrite = new AccessTestAction() {
273       @Override
274       public Void run() throws Exception {
275         checkGlobalPerms(TEST_UTIL, Permission.Action.READ, Permission.Action.WRITE);
276         return null;
277       }
278     };
279 
280     verifyAllowed(checkGlobalReadWrite, SUPERUSER, USER_ADMIN);
281     verifyDenied(checkGlobalReadWrite, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
282       USER_NONE);
283 
284     AccessTestAction checkTableAdmin = new AccessTestAction() {
285       @Override
286       public Void run() throws Exception {
287         checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null,
288           Permission.Action.ADMIN);
289         return null;
290       }
291     };
292 
293     verifyAllowed(checkTableAdmin, SUPERUSER, USER_ADMIN, USER_OWNER);
294     verifyDenied(checkTableAdmin, USER_CREATE, USER_RW, USER_RO, USER_QUAL, USER_NONE);
295 
296     AccessTestAction checkTableCreate = new AccessTestAction() {
297       @Override
298       public Void run() throws Exception {
299         checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null,
300           Permission.Action.CREATE);
301         return null;
302       }
303     };
304 
305     verifyAllowed(checkTableCreate, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
306     verifyDenied(checkTableCreate, USER_RW, USER_RO, USER_QUAL, USER_NONE);
307 
308     AccessTestAction checkTableRead = new AccessTestAction() {
309       @Override
310       public Void run() throws Exception {
311         checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null,
312           Permission.Action.READ);
313         return null;
314       }
315     };
316 
317     verifyAllowed(checkTableRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
318     verifyDenied(checkTableRead, USER_RW, USER_RO, USER_QUAL, USER_NONE);
319 
320     AccessTestAction checkTableReadWrite = new AccessTestAction() {
321       @Override
322       public Void run() throws Exception {
323         checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null,
324           Permission.Action.READ, Permission.Action.WRITE);
325         return null;
326       }
327     };
328 
329     verifyAllowed(checkTableReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
330     verifyDenied(checkTableReadWrite, USER_RW, USER_RO, USER_QUAL, USER_NONE);
331 
332     AccessTestAction checkColumnRead = new AccessTestAction() {
333       @Override
334       public Void run() throws Exception {
335         checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
336           Permission.Action.READ);
337         return null;
338       }
339     };
340 
341     verifyAllowed(checkColumnRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
342       USER_RO);
343     verifyDenied(checkColumnRead, USER_QUAL, USER_NONE);
344 
345     AccessTestAction checkColumnReadWrite = new AccessTestAction() {
346       @Override
347       public Void run() throws Exception {
348         checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
349           Permission.Action.READ, Permission.Action.WRITE);
350         return null;
351       }
352     };
353 
354     verifyAllowed(checkColumnReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
355       USER_RW);
356     verifyDenied(checkColumnReadWrite, USER_RO, USER_QUAL, USER_NONE);
357 
358     AccessTestAction checkQualifierRead = new AccessTestAction() {
359       @Override
360       public Void run() throws Exception {
361         checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, TEST_Q1,
362           Permission.Action.READ);
363         return null;
364       }
365     };
366 
367     verifyAllowed(checkQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
368       USER_RO, USER_QUAL);
369     verifyDenied(checkQualifierRead, USER_NONE);
370 
371     AccessTestAction checkQualifierReadWrite = new AccessTestAction() {
372       @Override
373       public Void run() throws Exception {
374         checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, TEST_Q1,
375           Permission.Action.READ, Permission.Action.WRITE);
376         return null;
377       }
378     };
379 
380     verifyAllowed(checkQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
381       USER_RW, USER_QUAL);
382     verifyDenied(checkQualifierReadWrite, USER_RO, USER_NONE);
383 
384     AccessTestAction checkMultiQualifierRead = new AccessTestAction() {
385       @Override
386       public Void run() throws Exception {
387         checkTablePerms(TEST_UTIL, testTable.getTableName(), new Permission[] {
388           new TablePermission(testTable.getTableName(), TEST_FAMILY, TEST_Q1,
389             Permission.Action.READ),
390           new TablePermission(testTable.getTableName(), TEST_FAMILY, TEST_Q2,
391             Permission.Action.READ), });
392         return null;
393       }
394     };
395 
396     verifyAllowed(checkMultiQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
397       USER_RW, USER_RO);
398     verifyDenied(checkMultiQualifierRead, USER_QUAL, USER_NONE);
399 
400     AccessTestAction checkMultiQualifierReadWrite = new AccessTestAction() {
401       @Override
402       public Void run() throws Exception {
403         checkTablePerms(TEST_UTIL, testTable.getTableName(), new Permission[] {
404           new TablePermission(testTable.getTableName(), TEST_FAMILY, TEST_Q1,
405               Permission.Action.READ, Permission.Action.WRITE),
406           new TablePermission(testTable.getTableName(), TEST_FAMILY, TEST_Q2,
407               Permission.Action.READ, Permission.Action.WRITE), });
408         return null;
409       }
410     };
411 
412     verifyAllowed(checkMultiQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
413       USER_RW);
414     verifyDenied(checkMultiQualifierReadWrite, USER_RO, USER_QUAL, USER_NONE);
415   }
416 
417   /** Test grants and revocations with authorization disabled */
418   @Test
419   public void testPassiveGrantRevoke() throws Exception {
420 
421     // Add a test user
422 
423     User tblUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser",
424       new String[0]);
425 
426     // If we check now, the test user won't have permissions
427 
428     AccessTestAction checkTableRead = new AccessTestAction() {
429       @Override
430       public Void run() throws Exception {
431         checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
432           Permission.Action.READ);
433         return null;
434       }
435     };
436 
437     verifyDenied(tblUser, checkTableRead);
438 
439     // An actual read won't be denied
440 
441     AccessTestAction tableRead = new AccessTestAction() {
442       @Override
443       public Void run() throws Exception {
444         try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
445              Table t = conn.getTable(testTable.getTableName())) {
446           t.get(new Get(TEST_ROW).addFamily(TEST_FAMILY));
447         }
448         return null;
449       }
450     };
451 
452     verifyAllowed(tblUser, tableRead);
453 
454     // Grant read perms to the test user
455 
456     grantOnTable(TEST_UTIL, tblUser.getShortName(), testTable.getTableName(), TEST_FAMILY,
457       null, Permission.Action.READ);
458 
459     // Now both the permission check and actual op will succeed
460 
461     verifyAllowed(tblUser, checkTableRead);
462     verifyAllowed(tblUser, tableRead);
463 
464     // Revoke read perms from the test user
465 
466     revokeFromTable(TEST_UTIL, tblUser.getShortName(), testTable.getTableName(), TEST_FAMILY,
467       null, Permission.Action.READ);
468 
469     // Now the permission check will indicate revocation but the actual op will still succeed
470 
471     verifyDenied(tblUser, checkTableRead);
472     verifyAllowed(tblUser, tableRead);
473   }
474 
475   /** Test master observer */
476   @Test
477   public void testPassiveMasterOperations() throws Exception {
478 
479     // preCreateTable
480     verifyAllowed(new AccessTestAction() {
481       @Override
482       public Object run() throws Exception {
483         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
484         htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
485         ACCESS_CONTROLLER.preCreateTable(ObserverContext.createAndPrepare(CP_ENV, null), htd,
486           null);
487         return null;
488       }
489     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
490 
491     // preModifyTable
492     verifyAllowed(new AccessTestAction() {
493       @Override
494       public Object run() throws Exception {
495         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
496         htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
497         htd.addFamily(new HColumnDescriptor(TEST_FAMILY2));
498         ACCESS_CONTROLLER.preModifyTable(ObserverContext.createAndPrepare(CP_ENV, null),
499           testTable.getTableName(), htd);
500         return null;
501       }
502     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
503 
504     // preDeleteTable
505     verifyAllowed(new AccessTestAction() {
506       @Override
507       public Object run() throws Exception {
508         ACCESS_CONTROLLER.preDeleteTable(ObserverContext.createAndPrepare(CP_ENV, null),
509           testTable.getTableName());
510         return null;
511       }
512     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
513 
514     // preTruncateTable
515     verifyAllowed(new AccessTestAction() {
516       @Override
517       public Object run() throws Exception {
518         ACCESS_CONTROLLER.preTruncateTable(ObserverContext.createAndPrepare(CP_ENV, null),
519           testTable.getTableName());
520         return null;
521       }
522     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
523 
524     // preAddColumn
525     verifyAllowed(new AccessTestAction() {
526       @Override
527       public Object run() throws Exception {
528         HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
529         ACCESS_CONTROLLER.preAddColumn(ObserverContext.createAndPrepare(CP_ENV, null),
530           testTable.getTableName(), hcd);
531         return null;
532       }
533     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
534 
535     // preModifyColumn
536     verifyAllowed(new AccessTestAction() {
537       @Override
538       public Object run() throws Exception {
539         HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY2);
540         ACCESS_CONTROLLER.preModifyColumn(ObserverContext.createAndPrepare(CP_ENV, null),
541           testTable.getTableName(), hcd);
542         return null;
543       }
544     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
545 
546     // preDeleteColumn
547     verifyAllowed(new AccessTestAction() {
548       @Override
549       public Object run() throws Exception {
550         ACCESS_CONTROLLER.preDeleteColumn(ObserverContext.createAndPrepare(CP_ENV, null),
551           testTable.getTableName(), TEST_FAMILY2);
552         return null;
553       }
554     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
555 
556     // preEnableTable
557     verifyAllowed(new AccessTestAction() {
558       @Override
559       public Object run() throws Exception {
560         ACCESS_CONTROLLER.preEnableTable(ObserverContext.createAndPrepare(CP_ENV, null),
561           testTable.getTableName());
562         return null;
563       }
564     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
565 
566     // preDisableTable
567     verifyAllowed(new AccessTestAction() {
568       @Override
569       public Object run() throws Exception {
570         ACCESS_CONTROLLER.preDisableTable(ObserverContext.createAndPrepare(CP_ENV, null),
571           testTable.getTableName());
572         return null;
573       }
574     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
575 
576     // preMove
577     verifyAllowed(new AccessTestAction() {
578       @Override
579       public Object run() throws Exception {
580         HRegionInfo region = new HRegionInfo(testTable.getTableName());
581         ServerName srcServer = ServerName.valueOf("1.1.1.1", 1, 0);
582         ServerName destServer = ServerName.valueOf("2.2.2.2", 2, 0);
583         ACCESS_CONTROLLER.preMove(ObserverContext.createAndPrepare(CP_ENV, null), region,
584           srcServer, destServer);
585         return null;
586       }
587     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
588 
589     // preAssign
590     verifyAllowed(new AccessTestAction() {
591       @Override
592       public Object run() throws Exception {
593         HRegionInfo region = new HRegionInfo(testTable.getTableName());
594         ACCESS_CONTROLLER.preAssign(ObserverContext.createAndPrepare(CP_ENV, null), region);
595         return null;
596       }
597     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
598 
599     // preUnassign
600     verifyAllowed(new AccessTestAction() {
601       @Override
602       public Object run() throws Exception {
603         HRegionInfo region = new HRegionInfo(testTable.getTableName());
604         ACCESS_CONTROLLER.preUnassign(ObserverContext.createAndPrepare(CP_ENV, null), region,
605           true);
606         return null;
607       }
608     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
609 
610     // preBalance
611     verifyAllowed(new AccessTestAction() {
612       @Override
613       public Object run() throws Exception {
614         ACCESS_CONTROLLER.preBalance(ObserverContext.createAndPrepare(CP_ENV, null));
615         return null;
616       }
617     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
618 
619     // preBalanceSwitch
620     verifyAllowed(new AccessTestAction() {
621       @Override
622       public Object run() throws Exception {
623         ACCESS_CONTROLLER.preBalanceSwitch(ObserverContext.createAndPrepare(CP_ENV, null),
624           true);
625         return null;
626       }
627     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
628 
629     // preSnapshot
630     verifyAllowed(new AccessTestAction() {
631       @Override
632       public Object run() throws Exception {
633         SnapshotDescription snapshot = SnapshotDescription.newBuilder()
634           .setName("foo")
635           .build();
636         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
637         ACCESS_CONTROLLER.preSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
638           snapshot, htd);
639         return null;
640       }
641     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
642 
643     // preCloneSnapshot
644     verifyAllowed(new AccessTestAction() {
645       @Override
646       public Object run() throws Exception {
647         SnapshotDescription snapshot = SnapshotDescription.newBuilder()
648           .setName("foo")
649           .build();
650         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
651         ACCESS_CONTROLLER.preCloneSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
652           snapshot, htd);
653         return null;
654       }
655     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
656 
657     // preRestoreSnapshot
658     verifyAllowed(new AccessTestAction() {
659       @Override
660       public Object run() throws Exception {
661         SnapshotDescription snapshot = SnapshotDescription.newBuilder()
662           .setName("foo")
663           .build();
664         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
665         ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
666           snapshot, htd);
667         return null;
668       }
669     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
670 
671     // preDeleteSnapshot
672     verifyAllowed(new AccessTestAction() {
673       @Override
674       public Object run() throws Exception {
675         SnapshotDescription snapshot = SnapshotDescription.newBuilder()
676           .setName("foo")
677           .build();
678         ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContext.createAndPrepare(CP_ENV, null),
679           snapshot);
680         return null;
681       }
682     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
683 
684     // preGetTableDescriptors
685     verifyAllowed(new AccessTestAction() {
686       @Override
687       public Object run() throws Exception {
688         List<TableName> tableNamesList = Lists.newArrayList();
689         tableNamesList.add(testTable.getTableName());
690         List<HTableDescriptor> descriptors = Lists.newArrayList();
691         ACCESS_CONTROLLER.preGetTableDescriptors(ObserverContext.createAndPrepare(CP_ENV, null),
692           tableNamesList, descriptors, ".+");
693         return null;
694       }
695     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
696 
697     // preGetTableNames
698     verifyAllowed(new AccessTestAction() {
699       @Override
700       public Object run() throws Exception {
701         List<HTableDescriptor> descriptors = Lists.newArrayList();
702         ACCESS_CONTROLLER.preGetTableNames(ObserverContext.createAndPrepare(CP_ENV, null),
703           descriptors, ".+");
704         return null;
705       }
706     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
707 
708     // preCreateNamespace
709     verifyAllowed(new AccessTestAction() {
710       @Override
711       public Object run() throws Exception {
712         NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
713         ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
714           ns);
715         return null;
716       }
717     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
718 
719     // preDeleteNamespace
720     verifyAllowed(new AccessTestAction() {
721       @Override
722       public Object run() throws Exception {
723         ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
724           "test");
725         return null;
726       }
727     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
728 
729     // preModifyNamespace
730     verifyAllowed(new AccessTestAction() {
731       @Override
732       public Object run() throws Exception {
733         NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
734         ACCESS_CONTROLLER.preModifyNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
735           ns);
736         return null;
737       }
738     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
739 
740     // preGetNamespaceDescriptor
741     verifyAllowed(new AccessTestAction() {
742       @Override
743       public Object run() throws Exception {
744         ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContext.createAndPrepare(CP_ENV,
745             null),
746           "test");
747         return null;
748       }
749     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
750 
751     // preListNamespaceDescriptors
752     verifyAllowed(new AccessTestAction() {
753       @Override
754       public Object run() throws Exception {
755         List<NamespaceDescriptor> descriptors = Lists.newArrayList();
756         ACCESS_CONTROLLER.preListNamespaceDescriptors(ObserverContext.createAndPrepare(CP_ENV,
757             null),
758           descriptors);
759         return null;
760       }
761     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
762   }
763 
764   /** Test region server observer */
765   @Test
766   public void testPassiveRegionServerOperations() throws Exception {
767     // preStopRegionServer
768     verifyAllowed(new AccessTestAction() {
769       @Override
770       public Object run() throws Exception {
771         ACCESS_CONTROLLER.preStopRegionServer(ObserverContext.createAndPrepare(RSCP_ENV, null));
772         return null;
773       }
774     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
775 
776     // preMerge
777     verifyAllowed(new AccessTestAction() {
778       @Override
779       public Object run() throws Exception {
780         HTableDescriptor htd = new HTableDescriptor(testTable.getTableName());
781         Region region_a = mock(Region.class);
782         when(region_a.getTableDesc()).thenReturn(htd);
783         Region region_b = mock(Region.class);
784         when(region_b.getTableDesc()).thenReturn(htd);
785         ACCESS_CONTROLLER.preMerge(ObserverContext.createAndPrepare(RSCP_ENV, null), region_a,
786           region_b);
787         return null;
788       }
789     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
790 
791     // preRollWALWriterRequest
792     verifyAllowed(new AccessTestAction() {
793       @Override
794       public Object run() throws Exception {
795         ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContext.createAndPrepare(RSCP_ENV,
796           null));
797         return null;
798       }
799     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
800 
801   }
802 
803   /** Test region observer */
804   @Test
805   public void testPassiveRegionOperations() throws Exception {
806 
807     // preOpen
808     verifyAllowed(new AccessTestAction() {
809       @Override
810       public Object run() throws Exception {
811         ACCESS_CONTROLLER.preOpen(ObserverContext.createAndPrepare(RCP_ENV, null));
812         return null;
813       }
814     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
815 
816     // preFlush
817     verifyAllowed(new AccessTestAction() {
818       @Override
819       public Object run() throws Exception {
820         ACCESS_CONTROLLER.preFlush(ObserverContext.createAndPrepare(RCP_ENV, null));
821         return null;
822       }
823     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
824 
825     // preSplit
826     verifyAllowed(new AccessTestAction() {
827       @Override
828       public Object run() throws Exception {
829         ACCESS_CONTROLLER.preSplit(ObserverContext.createAndPrepare(RCP_ENV, null));
830         return null;
831       }
832     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
833 
834     // preGetClosestRowBefore
835     verifyAllowed(new AccessTestAction() {
836       @Override
837       public Object run() throws Exception {
838         ACCESS_CONTROLLER.preGetClosestRowBefore(ObserverContext.createAndPrepare(RCP_ENV, null),
839           TEST_ROW, TEST_FAMILY, new Result());
840         return null;
841       }
842     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
843 
844     // preGetOp
845     verifyAllowed(new AccessTestAction() {
846       @Override
847       public Object run() throws Exception {
848         List<Cell> cells = Lists.newArrayList();
849         ACCESS_CONTROLLER.preGetOp(ObserverContext.createAndPrepare(RCP_ENV, null),
850           new Get(TEST_ROW), cells);
851         return null;
852       }
853     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
854 
855     // preExists
856     verifyAllowed(new AccessTestAction() {
857       @Override
858       public Object run() throws Exception {
859         ACCESS_CONTROLLER.preExists(ObserverContext.createAndPrepare(RCP_ENV, null),
860           new Get(TEST_ROW), true);
861         return null;
862       }
863     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
864 
865     // prePut
866     verifyAllowed(new AccessTestAction() {
867       @Override
868       public Object run() throws Exception {
869         ACCESS_CONTROLLER.prePut(ObserverContext.createAndPrepare(RCP_ENV, null),
870           new Put(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
871         return null;
872       }
873     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
874 
875     // preDelete
876     verifyAllowed(new AccessTestAction() {
877       @Override
878       public Object run() throws Exception {
879         ACCESS_CONTROLLER.preDelete(ObserverContext.createAndPrepare(RCP_ENV, null),
880           new Delete(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
881         return null;
882       }
883     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
884 
885     // preBatchMutate
886     verifyAllowed(new AccessTestAction() {
887       @Override
888       public Object run() throws Exception {
889         ACCESS_CONTROLLER.preBatchMutate(ObserverContext.createAndPrepare(RCP_ENV, null),
890           new MiniBatchOperationInProgress<Mutation>(null, null, null, 0, 0));
891         return null;
892       }
893     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
894 
895     // preCheckAndPut
896     verifyAllowed(new AccessTestAction() {
897       @Override
898       public Object run() throws Exception {
899         ACCESS_CONTROLLER.preCheckAndPut(ObserverContext.createAndPrepare(RCP_ENV, null),
900           TEST_ROW, TEST_FAMILY, TEST_Q1, CompareFilter.CompareOp.EQUAL,
901           new BinaryComparator("foo".getBytes()), new Put(TEST_ROW), true);
902         return null;
903       }
904     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
905 
906     // preCheckAndDelete
907     verifyAllowed(new AccessTestAction() {
908       @Override
909       public Object run() throws Exception {
910         ACCESS_CONTROLLER.preCheckAndDelete(ObserverContext.createAndPrepare(RCP_ENV, null),
911           TEST_ROW, TEST_FAMILY, TEST_Q1, CompareFilter.CompareOp.EQUAL,
912           new BinaryComparator("foo".getBytes()), new Delete(TEST_ROW), true);
913         return null;
914       }
915     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
916 
917     // preAppend
918     verifyAllowed(new AccessTestAction() {
919       @Override
920       public Object run() throws Exception {
921         ACCESS_CONTROLLER.preAppend(ObserverContext.createAndPrepare(RCP_ENV, null),
922           new Append(TEST_ROW));
923         return null;
924       }
925     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
926 
927     // preIncrement
928     verifyAllowed(new AccessTestAction() {
929       @Override
930       public Object run() throws Exception {
931         ACCESS_CONTROLLER.preIncrement(ObserverContext.createAndPrepare(RCP_ENV, null),
932           new Increment(TEST_ROW));
933         return null;
934       }
935     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
936 
937     // preScannerOpen
938     verifyAllowed(new AccessTestAction() {
939       @Override
940       public Object run() throws Exception {
941         ACCESS_CONTROLLER.preScannerOpen(ObserverContext.createAndPrepare(RCP_ENV, null),
942           new Scan(), mock(RegionScanner.class));
943         return null;
944       }
945     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
946 
947     // preBulkLoadHFile
948     verifyAllowed(new AccessTestAction() {
949       @Override
950       public Object run() throws Exception {
951         List<Pair<byte[], String>> paths = Lists.newArrayList();
952         ACCESS_CONTROLLER.preBulkLoadHFile(ObserverContext.createAndPrepare(RCP_ENV, null),
953           paths);
954         return null;
955       }
956     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
957 
958   }
959 
960   @Test
961   public void testPassiveCellPermissions() throws Exception {
962     final Configuration conf = TEST_UTIL.getConfiguration();
963 
964     // store two sets of values, one store with a cell level ACL, and one without
965     verifyAllowed(new AccessTestAction() {
966       @Override
967       public Object run() throws Exception {
968         try(Connection connection = ConnectionFactory.createConnection(conf);
969             Table t = connection.getTable(testTable.getTableName())) {
970           Put p;
971           // with ro ACL
972           p = new Put(TEST_ROW).add(TEST_FAMILY, TEST_Q1, ZERO);
973           p.setACL(USER_NONE.getShortName(), new Permission(Action.READ));
974           t.put(p);
975           // with rw ACL
976           p = new Put(TEST_ROW).add(TEST_FAMILY, TEST_Q2, ZERO);
977           p.setACL(USER_NONE.getShortName(), new Permission(Action.READ, Action.WRITE));
978           t.put(p);
979           // no ACL
980           p = new Put(TEST_ROW)
981             .add(TEST_FAMILY, TEST_Q3, ZERO)
982             .add(TEST_FAMILY, TEST_Q4, ZERO);
983           t.put(p);
984         }
985         return null;
986       }
987     }, USER_OWNER);
988 
989     // check that a scan over the test data returns the expected number of KVs
990 
991     final List<Cell> scanResults = Lists.newArrayList();
992 
993     AccessTestAction scanAction = new AccessTestAction() {
994       @Override
995       public List<Cell> run() throws Exception {
996         Scan scan = new Scan();
997         scan.setStartRow(TEST_ROW);
998         scan.setStopRow(Bytes.add(TEST_ROW, new byte[]{ 0 } ));
999         scan.addFamily(TEST_FAMILY);
1000         Connection connection = ConnectionFactory.createConnection(conf);
1001         Table t = connection.getTable(testTable.getTableName());
1002         try {
1003           ResultScanner scanner = t.getScanner(scan);
1004           Result result = null;
1005           do {
1006             result = scanner.next();
1007             if (result != null) {
1008               scanResults.addAll(result.listCells());
1009             }
1010           } while (result != null);
1011         } finally {
1012           t.close();
1013           connection.close();
1014         }
1015         return scanResults;
1016       }
1017     };
1018 
1019     // owner will see all values
1020     scanResults.clear();
1021     verifyAllowed(scanAction, USER_OWNER);
1022     assertEquals(4, scanResults.size());
1023 
1024     // other user will also see 4 values
1025     // if cell filtering was active, we would only see 2 values
1026     scanResults.clear();
1027     verifyAllowed(scanAction, USER_NONE);
1028     assertEquals(4, scanResults.size());
1029   }
1030 
1031 }