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