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.Admin;
39  import org.apache.hadoop.hbase.client.Append;
40  import org.apache.hadoop.hbase.client.Connection;
41  import org.apache.hadoop.hbase.client.ConnectionFactory;
42  import org.apache.hadoop.hbase.client.Delete;
43  import org.apache.hadoop.hbase.client.Durability;
44  import org.apache.hadoop.hbase.client.Get;
45  import org.apache.hadoop.hbase.client.Increment;
46  import org.apache.hadoop.hbase.client.Mutation;
47  import org.apache.hadoop.hbase.client.Put;
48  import org.apache.hadoop.hbase.client.Result;
49  import org.apache.hadoop.hbase.client.ResultScanner;
50  import org.apache.hadoop.hbase.client.Scan;
51  import org.apache.hadoop.hbase.client.Table;
52  import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
53  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
54  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
55  import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
56  import org.apache.hadoop.hbase.filter.BinaryComparator;
57  import org.apache.hadoop.hbase.filter.CompareFilter;
58  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
59  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
60  import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
61  import org.apache.hadoop.hbase.regionserver.Region;
62  import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
63  import org.apache.hadoop.hbase.regionserver.RegionScanner;
64  import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
65  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
66  import org.apache.hadoop.hbase.security.User;
67  import org.apache.hadoop.hbase.security.access.Permission.Action;
68  import org.apache.hadoop.hbase.testclassification.LargeTests;
69  import org.apache.hadoop.hbase.util.Bytes;
70  import org.apache.hadoop.hbase.util.Pair;
71  import org.apache.hadoop.hbase.util.TestTableName;
72  import org.apache.log4j.Level;
73  import org.apache.log4j.Logger;
74  import org.junit.After;
75  import org.junit.AfterClass;
76  import org.junit.Before;
77  import org.junit.BeforeClass;
78  import org.junit.Rule;
79  import org.junit.Test;
80  import org.junit.experimental.categories.Category;
81  
82  import com.google.common.collect.Lists;
83  
84  @Category(LargeTests.class)
85  public class TestWithDisabledAuthorization extends SecureTestUtil {
86    private static final Log LOG = LogFactory.getLog(TestWithDisabledAuthorization.class);
87  
88    static {
89      Logger.getLogger(AccessController.class).setLevel(Level.TRACE);
90      Logger.getLogger(AccessControlFilter.class).setLevel(Level.TRACE);
91      Logger.getLogger(TableAuthManager.class).setLevel(Level.TRACE);
92    }
93  
94    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
95  
96    private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
97    private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
98    private static final byte[] TEST_ROW = Bytes.toBytes("testrow");
99    private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
100   private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
101   private static final byte[] TEST_Q3 = Bytes.toBytes("q3");
102   private static final byte[] TEST_Q4 = Bytes.toBytes("q4");
103   private static final byte[] ZERO = Bytes.toBytes(0L);
104 
105   private static MasterCoprocessorEnvironment CP_ENV;
106   private static AccessController ACCESS_CONTROLLER;
107   private static RegionServerCoprocessorEnvironment RSCP_ENV;
108   private RegionCoprocessorEnvironment RCP_ENV;
109 
110   @Rule public TestTableName TEST_TABLE = new TestTableName();
111 
112   // default users
113   
114   // superuser
115   private static User SUPERUSER;
116   // user granted with all global permission
117   private static User USER_ADMIN;
118   // user with rw permissions on column family.
119   private static User USER_RW;
120   // user with read-only permissions
121   private static User USER_RO;
122   // user is table owner. will have all permissions on table
123   private static User USER_OWNER;
124   // user with create table permissions alone
125   private static User USER_CREATE;
126   // user with no permissions
127   private static User USER_NONE;
128   // user with only partial read-write perms (on family:q1 only)
129   private static User USER_QUAL;
130 
131   @BeforeClass
132   public static void setupBeforeClass() throws Exception {
133     Configuration conf = TEST_UTIL.getConfiguration();
134     // Enable security
135     enableSecurity(conf);
136     // We expect 0.98 cell ACL semantics
137     conf.setBoolean(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, false);
138     // Enable EXEC permission checking
139     conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true);
140     // Verify enableSecurity sets up what we require
141     verifyConfiguration(conf);
142 
143     // Now, DISABLE only active authorization
144     conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
145 
146     // Start the minicluster
147     TEST_UTIL.startMiniCluster();
148     MasterCoprocessorHost cpHost =
149         TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
150     cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
151     ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
152     CP_ENV = cpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
153       Coprocessor.PRIORITY_HIGHEST, 1, conf);
154     RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
155       .getRegionServerCoprocessorHost();
156     RSCP_ENV = rsHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
157       Coprocessor.PRIORITY_HIGHEST, 1, conf);
158 
159     // Wait for the ACL table to become available
160     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
161 
162     // create a set of test users
163     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
164     USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]);
165     USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
166     USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]);
167     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
168     USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
169     USER_QUAL = User.createUserForTesting(conf, "rwpartial", new String[0]);
170     USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]);
171   }
172 
173   @AfterClass
174   public static void tearDownAfterClass() throws Exception {
175     TEST_UTIL.shutdownMiniCluster();
176   }
177 
178   @Before
179   public void setUp() throws Exception {
180     // Create the test table (owner added to the _acl_ table)
181     Admin admin = TEST_UTIL.getHBaseAdmin();
182     HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
183     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
184     hcd.setMaxVersions(100);
185     htd.addFamily(hcd);
186     htd.setOwner(USER_OWNER);
187     admin.createTable(htd, new byte[][] { Bytes.toBytes("s") });
188     TEST_UTIL.waitUntilAllRegionsAssigned(TEST_TABLE.getTableName());
189 
190     Region region = TEST_UTIL.getHBaseCluster().getRegions(TEST_TABLE.getTableName()).get(0);
191     RegionCoprocessorHost rcpHost = region.getCoprocessorHost();
192     RCP_ENV = rcpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER,
193       Coprocessor.PRIORITY_HIGHEST, 1, TEST_UTIL.getConfiguration());
194 
195     // Set up initial grants
196 
197     grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(),
198       Permission.Action.ADMIN,
199       Permission.Action.CREATE,
200       Permission.Action.READ,
201       Permission.Action.WRITE);
202 
203     grantOnTable(TEST_UTIL, USER_RW.getShortName(),
204       TEST_TABLE.getTableName(), TEST_FAMILY, null,
205       Permission.Action.READ,
206       Permission.Action.WRITE);
207 
208     // USER_CREATE is USER_RW plus CREATE permissions
209     grantOnTable(TEST_UTIL, USER_CREATE.getShortName(),
210       TEST_TABLE.getTableName(), null, null,
211       Permission.Action.CREATE,
212       Permission.Action.READ,
213       Permission.Action.WRITE);
214 
215     grantOnTable(TEST_UTIL, USER_RO.getShortName(),
216       TEST_TABLE.getTableName(), TEST_FAMILY, null,
217       Permission.Action.READ);
218 
219     grantOnTable(TEST_UTIL, USER_QUAL.getShortName(),
220       TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
221       Permission.Action.READ,
222       Permission.Action.WRITE);
223 
224     assertEquals(5, AccessControlLists.getTablePermissions(TEST_UTIL.getConfiguration(),
225       TEST_TABLE.getTableName()).size());
226   }
227 
228   @After
229   public void tearDown() throws Exception {
230     // Clean the _acl_ table
231     try {
232       deleteTable(TEST_UTIL, TEST_TABLE.getTableName());
233     } catch (TableNotFoundException ex) {
234       // Test deleted the table, no problem
235       LOG.info("Test deleted table " + TEST_TABLE.getTableName());
236     }
237     // Verify all table/namespace permissions are erased
238     assertEquals(0, AccessControlLists.getTablePermissions(TEST_UTIL.getConfiguration(),
239       TEST_TABLE.getTableName()).size());
240     assertEquals(0, AccessControlLists.getNamespacePermissions(TEST_UTIL.getConfiguration(),
241       TEST_TABLE.getTableName().getNamespaceAsString()).size());
242   }
243 
244   @Test
245   public void testCheckPermissions() throws Exception {
246 
247     AccessTestAction checkGlobalAdmin = new AccessTestAction() {
248       @Override
249       public Void run() throws Exception {
250         checkGlobalPerms(TEST_UTIL, Permission.Action.ADMIN);
251         return null;
252       }
253     };
254 
255     verifyAllowed(checkGlobalAdmin, SUPERUSER, USER_ADMIN);
256     verifyDenied(checkGlobalAdmin, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
257       USER_NONE);
258 
259     AccessTestAction checkGlobalRead = new AccessTestAction() {
260       @Override
261       public Void run() throws Exception {
262         checkGlobalPerms(TEST_UTIL, Permission.Action.READ);
263         return null;
264       }
265     };
266 
267     verifyAllowed(checkGlobalRead, SUPERUSER, USER_ADMIN);
268     verifyDenied(checkGlobalRead, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
269       USER_NONE);
270 
271     AccessTestAction checkGlobalReadWrite = new AccessTestAction() {
272       @Override
273       public Void run() throws Exception {
274         checkGlobalPerms(TEST_UTIL, Permission.Action.READ, Permission.Action.WRITE);
275         return null;
276       }
277     };
278 
279     verifyAllowed(checkGlobalReadWrite, SUPERUSER, USER_ADMIN);
280     verifyDenied(checkGlobalReadWrite, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
281       USER_NONE);
282 
283     AccessTestAction checkTableAdmin = new AccessTestAction() {
284       @Override
285       public Void run() throws Exception {
286         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), null, null,
287           Permission.Action.ADMIN);
288         return null;
289       }
290     };
291 
292     verifyAllowed(checkTableAdmin, SUPERUSER, USER_ADMIN, USER_OWNER);
293     verifyDenied(checkTableAdmin, USER_CREATE, USER_RW, USER_RO, USER_QUAL, USER_NONE);
294 
295     AccessTestAction checkTableCreate = new AccessTestAction() {
296       @Override
297       public Void run() throws Exception {
298         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), null, null,
299           Permission.Action.CREATE);
300         return null;
301       }
302     };
303 
304     verifyAllowed(checkTableCreate, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
305     verifyDenied(checkTableCreate, USER_RW, USER_RO, USER_QUAL, USER_NONE);
306 
307     AccessTestAction checkTableRead = new AccessTestAction() {
308       @Override
309       public Void run() throws Exception {
310         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), null, null,
311           Permission.Action.READ);
312         return null;
313       }
314     };
315 
316     verifyAllowed(checkTableRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
317     verifyDenied(checkTableRead, USER_RW, USER_RO, USER_QUAL, USER_NONE);
318 
319     AccessTestAction checkTableReadWrite = new AccessTestAction() {
320       @Override
321       public Void run() throws Exception {
322         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), null, null,
323           Permission.Action.READ, Permission.Action.WRITE);
324         return null;
325       }
326     };
327 
328     verifyAllowed(checkTableReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
329     verifyDenied(checkTableReadWrite, USER_RW, USER_RO, USER_QUAL, USER_NONE);
330 
331     AccessTestAction checkColumnRead = new AccessTestAction() {
332       @Override
333       public Void run() throws Exception {
334         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), TEST_FAMILY, null,
335           Permission.Action.READ);
336         return null;
337       }
338     };
339 
340     verifyAllowed(checkColumnRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
341       USER_RO);
342     verifyDenied(checkColumnRead, USER_QUAL, USER_NONE);
343 
344     AccessTestAction checkColumnReadWrite = new AccessTestAction() {
345       @Override
346       public Void run() throws Exception {
347         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), TEST_FAMILY, null,
348           Permission.Action.READ, Permission.Action.WRITE);
349         return null;
350       }
351     };
352 
353     verifyAllowed(checkColumnReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
354       USER_RW);
355     verifyDenied(checkColumnReadWrite, USER_RO, USER_QUAL, USER_NONE);
356 
357     AccessTestAction checkQualifierRead = new AccessTestAction() {
358       @Override
359       public Void run() throws Exception {
360         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
361           Permission.Action.READ);
362         return null;
363       }
364     };
365 
366     verifyAllowed(checkQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
367       USER_RO, USER_QUAL);
368     verifyDenied(checkQualifierRead, USER_NONE);
369 
370     AccessTestAction checkQualifierReadWrite = new AccessTestAction() {
371       @Override
372       public Void run() throws Exception {
373         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
374           Permission.Action.READ, Permission.Action.WRITE);
375         return null;
376       }
377     };
378 
379     verifyAllowed(checkQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
380       USER_RW, USER_QUAL);
381     verifyDenied(checkQualifierReadWrite, USER_RO, USER_NONE);
382 
383     AccessTestAction checkMultiQualifierRead = new AccessTestAction() {
384       @Override
385       public Void run() throws Exception {
386         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), new Permission[] {
387           new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
388             Permission.Action.READ),
389           new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2,
390             Permission.Action.READ), });
391         return null;
392       }
393     };
394 
395     verifyAllowed(checkMultiQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
396       USER_RW, USER_RO);
397     verifyDenied(checkMultiQualifierRead, USER_QUAL, USER_NONE);
398 
399     AccessTestAction checkMultiQualifierReadWrite = new AccessTestAction() {
400       @Override
401       public Void run() throws Exception {
402         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), new Permission[] {
403             new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q1,
404               Permission.Action.READ, Permission.Action.WRITE),
405             new TablePermission(TEST_TABLE.getTableName(), TEST_FAMILY, TEST_Q2,
406               Permission.Action.READ, Permission.Action.WRITE), });
407         return null;
408       }
409     };
410 
411     verifyAllowed(checkMultiQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
412       USER_RW);
413     verifyDenied(checkMultiQualifierReadWrite, USER_RO, USER_QUAL, USER_NONE);
414   }
415 
416   /** Test grants and revocations with authorization disabled */
417   @Test
418   public void testPassiveGrantRevoke() throws Exception {
419 
420     // Add a test user
421 
422     User tblUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser",
423       new String[0]);
424 
425     // If we check now, the test user won't have permissions
426 
427     AccessTestAction checkTableRead = new AccessTestAction() {
428       @Override
429       public Void run() throws Exception {
430         checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(), TEST_FAMILY, null,
431           Permission.Action.READ);
432         return null;
433       }
434     };
435 
436     verifyDenied(tblUser, checkTableRead);
437 
438     // An actual read won't be denied
439 
440     AccessTestAction tableRead = new AccessTestAction() {
441       @Override
442       public Void run() throws Exception {
443         try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
444              Table t = conn.getTable(TEST_TABLE.getTableName())) {
445           t.get(new Get(TEST_ROW).addFamily(TEST_FAMILY));
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     // preGetTableNames
697     verifyAllowed(new AccessTestAction() {
698       @Override
699       public Object run() throws Exception {
700         List<HTableDescriptor> descriptors = Lists.newArrayList();
701         ACCESS_CONTROLLER.preGetTableNames(ObserverContext.createAndPrepare(CP_ENV, null),
702           descriptors, ".+");
703         return null;
704       }
705     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
706 
707     // preCreateNamespace
708     verifyAllowed(new AccessTestAction() {
709       @Override
710       public Object run() throws Exception {
711         NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
712         ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
713           ns);
714         return null;
715       }
716     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
717 
718     // preDeleteNamespace
719     verifyAllowed(new AccessTestAction() {
720       @Override
721       public Object run() throws Exception {
722         ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
723           "test");
724         return null;
725       }
726     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
727 
728     // preModifyNamespace
729     verifyAllowed(new AccessTestAction() {
730       @Override
731       public Object run() throws Exception {
732         NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
733         ACCESS_CONTROLLER.preModifyNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
734           ns);
735         return null;
736       }
737     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
738 
739     // preGetNamespaceDescriptor
740     verifyAllowed(new AccessTestAction() {
741       @Override
742       public Object run() throws Exception {
743         ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContext.createAndPrepare(CP_ENV,
744             null),
745           "test");
746         return null;
747       }
748     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
749 
750     // preListNamespaceDescriptors
751     verifyAllowed(new AccessTestAction() {
752       @Override
753       public Object run() throws Exception {
754         List<NamespaceDescriptor> descriptors = Lists.newArrayList();
755         ACCESS_CONTROLLER.preListNamespaceDescriptors(ObserverContext.createAndPrepare(CP_ENV,
756             null),
757           descriptors);
758         return null;
759       }
760     }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
761 
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(TEST_TABLE.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(TEST_TABLE.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(TEST_TABLE.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 }