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