001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.security.access;
019
020import static org.junit.Assert.assertEquals;
021
022import java.util.List;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.hbase.Cell;
025import org.apache.hadoop.hbase.CompareOperator;
026import org.apache.hadoop.hbase.Coprocessor;
027import org.apache.hadoop.hbase.HBaseClassTestRule;
028import org.apache.hadoop.hbase.HBaseTestingUtility;
029import org.apache.hadoop.hbase.HColumnDescriptor;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.HRegionInfo;
032import org.apache.hadoop.hbase.HTableDescriptor;
033import org.apache.hadoop.hbase.NamespaceDescriptor;
034import org.apache.hadoop.hbase.ServerName;
035import org.apache.hadoop.hbase.TableName;
036import org.apache.hadoop.hbase.TableNotFoundException;
037import org.apache.hadoop.hbase.TestTableName;
038import org.apache.hadoop.hbase.client.Admin;
039import org.apache.hadoop.hbase.client.Append;
040import org.apache.hadoop.hbase.client.Connection;
041import org.apache.hadoop.hbase.client.ConnectionFactory;
042import org.apache.hadoop.hbase.client.Delete;
043import org.apache.hadoop.hbase.client.Durability;
044import org.apache.hadoop.hbase.client.Get;
045import org.apache.hadoop.hbase.client.Increment;
046import org.apache.hadoop.hbase.client.Put;
047import org.apache.hadoop.hbase.client.Result;
048import org.apache.hadoop.hbase.client.ResultScanner;
049import org.apache.hadoop.hbase.client.Scan;
050import org.apache.hadoop.hbase.client.SnapshotDescription;
051import org.apache.hadoop.hbase.client.Table;
052import org.apache.hadoop.hbase.client.TableDescriptor;
053import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
054import org.apache.hadoop.hbase.coprocessor.ObserverContextImpl;
055import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
056import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
057import org.apache.hadoop.hbase.filter.BinaryComparator;
058import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
059import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
060import org.apache.hadoop.hbase.regionserver.HRegion;
061import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
062import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
063import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
064import org.apache.hadoop.hbase.security.User;
065import org.apache.hadoop.hbase.security.access.Permission.Action;
066import org.apache.hadoop.hbase.testclassification.LargeTests;
067import org.apache.hadoop.hbase.testclassification.SecurityTests;
068import org.apache.hadoop.hbase.util.Bytes;
069import org.apache.hadoop.hbase.util.Pair;
070import org.apache.hadoop.hbase.wal.WALEdit;
071import org.junit.After;
072import org.junit.AfterClass;
073import org.junit.Before;
074import org.junit.BeforeClass;
075import org.junit.ClassRule;
076import org.junit.Rule;
077import org.junit.Test;
078import org.junit.experimental.categories.Category;
079import org.slf4j.Logger;
080import org.slf4j.LoggerFactory;
081
082import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
083
084@Category({SecurityTests.class, LargeTests.class})
085public class TestWithDisabledAuthorization extends SecureTestUtil {
086
087  @ClassRule
088  public static final HBaseClassTestRule CLASS_RULE =
089      HBaseClassTestRule.forClass(TestWithDisabledAuthorization.class);
090
091  private static final Logger LOG = LoggerFactory.getLogger(TestWithDisabledAuthorization.class);
092  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
093
094  private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
095  private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
096  private static final byte[] TEST_ROW = Bytes.toBytes("testrow");
097  private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
098  private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
099  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    // Up the handlers; this test needs more than usual.
133    TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
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(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf);
153    RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
154      .getRegionServerCoprocessorHost();
155    RSCP_ENV = rsHost.createEnvironment(ACCESS_CONTROLLER, 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    Admin admin = TEST_UTIL.getAdmin();
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(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      deleteTable(TEST_UTIL, 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        try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
442             Table t = conn.getTable(TEST_TABLE.getTableName())) {
443          t.get(new Get(TEST_ROW).addFamily(TEST_FAMILY));
444        }
445        return null;
446      }
447    };
448
449    verifyAllowed(tblUser, tableRead);
450
451    // Grant read perms to the test user
452
453    grantOnTable(TEST_UTIL, tblUser.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY,
454      null, Permission.Action.READ);
455
456    // Now both the permission check and actual op will succeed
457
458    verifyAllowed(tblUser, checkTableRead);
459    verifyAllowed(tblUser, tableRead);
460
461    // Revoke read perms from the test user
462
463    revokeFromTable(TEST_UTIL, tblUser.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY,
464      null, Permission.Action.READ);
465
466    // Now the permission check will indicate revocation but the actual op will still succeed
467
468    verifyDenied(tblUser, checkTableRead);
469    verifyAllowed(tblUser, tableRead);
470  }
471
472  /** Test master observer */
473  @Test
474  public void testPassiveMasterOperations() throws Exception {
475
476    // preCreateTable
477    verifyAllowed(new AccessTestAction() {
478      @Override
479      public Object run() throws Exception {
480        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
481        htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
482        ACCESS_CONTROLLER.preCreateTable(ObserverContextImpl.createAndPrepare(CP_ENV), htd,
483          null);
484        return null;
485      }
486    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
487
488    // preModifyTable
489    verifyAllowed(new AccessTestAction() {
490      @Override
491      public Object run() throws Exception {
492        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
493        htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
494        htd.addFamily(new HColumnDescriptor(TEST_FAMILY2));
495        ACCESS_CONTROLLER.preModifyTable(ObserverContextImpl.createAndPrepare(CP_ENV),
496          TEST_TABLE.getTableName(), htd);
497        return null;
498      }
499    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
500
501    // preDeleteTable
502    verifyAllowed(new AccessTestAction() {
503      @Override
504      public Object run() throws Exception {
505        ACCESS_CONTROLLER.preDeleteTable(ObserverContextImpl.createAndPrepare(CP_ENV),
506          TEST_TABLE.getTableName());
507        return null;
508      }
509    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
510
511    // preTruncateTable
512    verifyAllowed(new AccessTestAction() {
513      @Override
514      public Object run() throws Exception {
515        ACCESS_CONTROLLER.preTruncateTable(ObserverContextImpl.createAndPrepare(CP_ENV),
516          TEST_TABLE.getTableName());
517        return null;
518      }
519    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
520
521    // preEnableTable
522    verifyAllowed(new AccessTestAction() {
523      @Override
524      public Object run() throws Exception {
525        ACCESS_CONTROLLER.preEnableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
526          TEST_TABLE.getTableName());
527        return null;
528      }
529    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
530
531    // preDisableTable
532    verifyAllowed(new AccessTestAction() {
533      @Override
534      public Object run() throws Exception {
535        ACCESS_CONTROLLER.preDisableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
536          TEST_TABLE.getTableName());
537        return null;
538      }
539    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
540
541    // preMove
542    verifyAllowed(new AccessTestAction() {
543      @Override
544      public Object run() throws Exception {
545        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
546        ServerName srcServer = ServerName.valueOf("1.1.1.1", 1, 0);
547        ServerName destServer = ServerName.valueOf("2.2.2.2", 2, 0);
548        ACCESS_CONTROLLER.preMove(ObserverContextImpl.createAndPrepare(CP_ENV), region,
549          srcServer, destServer);
550        return null;
551      }
552    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
553
554    // preAssign
555    verifyAllowed(new AccessTestAction() {
556      @Override
557      public Object run() throws Exception {
558        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
559        ACCESS_CONTROLLER.preAssign(ObserverContextImpl.createAndPrepare(CP_ENV), region);
560        return null;
561      }
562    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
563
564    // preUnassign
565    verifyAllowed(new AccessTestAction() {
566      @Override
567      public Object run() throws Exception {
568        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
569        ACCESS_CONTROLLER.preUnassign(ObserverContextImpl.createAndPrepare(CP_ENV), region,
570          true);
571        return null;
572      }
573    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
574
575    // preBalance
576    verifyAllowed(new AccessTestAction() {
577      @Override
578      public Object run() throws Exception {
579        ACCESS_CONTROLLER.preBalance(ObserverContextImpl.createAndPrepare(CP_ENV));
580        return null;
581      }
582    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
583
584    // preBalanceSwitch
585    verifyAllowed(new AccessTestAction() {
586      @Override
587      public Object run() throws Exception {
588        ACCESS_CONTROLLER.preBalanceSwitch(ObserverContextImpl.createAndPrepare(CP_ENV),
589          true);
590        return null;
591      }
592    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
593
594    // preSnapshot
595    verifyAllowed(new AccessTestAction() {
596      @Override
597      public Object run() throws Exception {
598        SnapshotDescription snapshot = new SnapshotDescription("foo");
599        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
600        ACCESS_CONTROLLER.preSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
601          snapshot, htd);
602        return null;
603      }
604    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
605
606    // preListSnapshot
607    verifyAllowed(new AccessTestAction() {
608      @Override
609      public Object run() throws Exception {
610        SnapshotDescription snapshot = new SnapshotDescription("foo");
611        ACCESS_CONTROLLER.preListSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
612          snapshot);
613        return null;
614      }
615    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
616
617    // preCloneSnapshot
618    verifyAllowed(new AccessTestAction() {
619      @Override
620      public Object run() throws Exception {
621        SnapshotDescription snapshot = new SnapshotDescription("foo");
622        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
623        ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
624          snapshot, htd);
625        return null;
626      }
627    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
628
629    // preRestoreSnapshot
630    verifyAllowed(new AccessTestAction() {
631      @Override
632      public Object run() throws Exception {
633        SnapshotDescription snapshot = new SnapshotDescription("foo");
634        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
635        ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
636          snapshot, htd);
637        return null;
638      }
639    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
640
641    // preDeleteSnapshot
642    verifyAllowed(new AccessTestAction() {
643      @Override
644      public Object run() throws Exception {
645        SnapshotDescription snapshot = new SnapshotDescription("foo");
646        ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
647          snapshot);
648        return null;
649      }
650    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
651
652    // preGetTableDescriptors
653    verifyAllowed(new AccessTestAction() {
654      @Override
655      public Object run() throws Exception {
656        List<TableName> tableNamesList = Lists.newArrayList();
657        tableNamesList.add(TEST_TABLE.getTableName());
658        List<TableDescriptor> descriptors = Lists.newArrayList();
659        ACCESS_CONTROLLER.preGetTableDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
660          tableNamesList, descriptors, ".+");
661        return null;
662      }
663    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
664
665    // preGetTableNames
666    verifyAllowed(new AccessTestAction() {
667      @Override
668      public Object run() throws Exception {
669        List<TableDescriptor> descriptors = Lists.newArrayList();
670        ACCESS_CONTROLLER.preGetTableNames(ObserverContextImpl.createAndPrepare(CP_ENV),
671          descriptors, ".+");
672        return null;
673      }
674    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
675
676    // preCreateNamespace
677    verifyAllowed(new AccessTestAction() {
678      @Override
679      public Object run() throws Exception {
680        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
681        ACCESS_CONTROLLER.preCreateNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
682          ns);
683        return null;
684      }
685    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
686
687    // preDeleteNamespace
688    verifyAllowed(new AccessTestAction() {
689      @Override
690      public Object run() throws Exception {
691        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
692          "test");
693        return null;
694      }
695    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
696
697    // preModifyNamespace
698    verifyAllowed(new AccessTestAction() {
699      @Override
700      public Object run() throws Exception {
701        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
702        ACCESS_CONTROLLER.preModifyNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
703          ns);
704        return null;
705      }
706    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
707
708    // preGetNamespaceDescriptor
709    verifyAllowed(new AccessTestAction() {
710      @Override
711      public Object run() throws Exception {
712        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContextImpl.createAndPrepare(CP_ENV),
713          "test");
714        return null;
715      }
716    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
717
718    // preListNamespaceDescriptors
719    verifyAllowed(new AccessTestAction() {
720      @Override
721      public Object run() throws Exception {
722        List<NamespaceDescriptor> descriptors = Lists.newArrayList();
723        ACCESS_CONTROLLER.preListNamespaceDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
724          descriptors);
725        return null;
726      }
727    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
728
729    // preSplit
730    verifyAllowed(new AccessTestAction() {
731      @Override
732      public Object run() throws Exception {
733        ACCESS_CONTROLLER.preSplitRegion(
734          ObserverContextImpl.createAndPrepare(CP_ENV),
735          TEST_TABLE.getTableName(),
736          Bytes.toBytes("ss"));
737        return null;
738      }
739    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
740
741    // preSetUserQuota
742    verifyAllowed(new AccessTestAction() {
743      @Override
744      public Object run() throws Exception {
745        ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
746          "testuser", null);
747        return null;
748      }
749    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
750
751    // preSetTableQuota
752    verifyAllowed(new AccessTestAction() {
753      @Override
754      public Object run() throws Exception {
755        ACCESS_CONTROLLER.preSetTableQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
756          TEST_TABLE.getTableName(), null);
757        return null;
758      }
759    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
760
761    // preSetNamespaceQuota
762    verifyAllowed(new AccessTestAction() {
763      @Override
764      public Object run() throws Exception {
765        ACCESS_CONTROLLER.preSetNamespaceQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
766          "test", null);
767        return null;
768      }
769    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
770
771  }
772
773  /** Test region server observer */
774  @Test
775  public void testPassiveRegionServerOperations() throws Exception {
776    // preStopRegionServer
777    verifyAllowed(new AccessTestAction() {
778      @Override
779      public Object run() throws Exception {
780        ACCESS_CONTROLLER.preStopRegionServer(ObserverContextImpl.createAndPrepare(RSCP_ENV));
781        return null;
782      }
783    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
784
785    // preRollWALWriterRequest
786    verifyAllowed(new AccessTestAction() {
787      @Override
788      public Object run() throws Exception {
789        ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContextImpl.createAndPrepare(RSCP_ENV));
790        return null;
791      }
792    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
793
794  }
795
796  /** Test region observer */
797  @Test
798  public void testPassiveRegionOperations() throws Exception {
799
800    // preOpen
801    verifyAllowed(new AccessTestAction() {
802      @Override
803      public Object run() throws Exception {
804        ACCESS_CONTROLLER.preOpen(ObserverContextImpl.createAndPrepare(RCP_ENV));
805        return null;
806      }
807    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
808
809    // preFlush
810    verifyAllowed(new AccessTestAction() {
811      @Override
812      public Object run() throws Exception {
813        ACCESS_CONTROLLER.preFlush(ObserverContextImpl.createAndPrepare(RCP_ENV),
814          FlushLifeCycleTracker.DUMMY);
815        return null;
816      }
817    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
818
819    // preGetOp
820    verifyAllowed(new AccessTestAction() {
821      @Override
822      public Object run() throws Exception {
823        List<Cell> cells = Lists.newArrayList();
824        ACCESS_CONTROLLER.preGetOp(ObserverContextImpl.createAndPrepare(RCP_ENV),
825          new Get(TEST_ROW), cells);
826        return null;
827      }
828    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
829
830    // preExists
831    verifyAllowed(new AccessTestAction() {
832      @Override
833      public Object run() throws Exception {
834        ACCESS_CONTROLLER.preExists(ObserverContextImpl.createAndPrepare(RCP_ENV),
835          new Get(TEST_ROW), true);
836        return null;
837      }
838    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
839
840    // prePut
841    verifyAllowed(new AccessTestAction() {
842      @Override
843      public Object run() throws Exception {
844        ACCESS_CONTROLLER.prePut(ObserverContextImpl.createAndPrepare(RCP_ENV),
845          new Put(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
846        return null;
847      }
848    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
849
850    // preDelete
851    verifyAllowed(new AccessTestAction() {
852      @Override
853      public Object run() throws Exception {
854        ACCESS_CONTROLLER.preDelete(ObserverContextImpl.createAndPrepare(RCP_ENV),
855          new Delete(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
856        return null;
857      }
858    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
859
860    // preBatchMutate
861    verifyAllowed(new AccessTestAction() {
862      @Override
863      public Object run() throws Exception {
864        ACCESS_CONTROLLER.preBatchMutate(ObserverContextImpl.createAndPrepare(RCP_ENV),
865          new MiniBatchOperationInProgress<>(null, null, null, 0, 0, 0));
866        return null;
867      }
868    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
869
870    // preCheckAndPut
871    verifyAllowed(new AccessTestAction() {
872      @Override
873      public Object run() throws Exception {
874        ACCESS_CONTROLLER.preCheckAndPut(ObserverContextImpl.createAndPrepare(RCP_ENV),
875          TEST_ROW, TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL,
876          new BinaryComparator("foo".getBytes()), new Put(TEST_ROW), true);
877        return null;
878      }
879    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
880
881    // preCheckAndDelete
882    verifyAllowed(new AccessTestAction() {
883      @Override
884      public Object run() throws Exception {
885        ACCESS_CONTROLLER.preCheckAndDelete(ObserverContextImpl.createAndPrepare(RCP_ENV),
886          TEST_ROW, TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL,
887          new BinaryComparator("foo".getBytes()), new Delete(TEST_ROW), true);
888        return null;
889      }
890    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
891
892    // preAppend
893    verifyAllowed(new AccessTestAction() {
894      @Override
895      public Object run() throws Exception {
896        ACCESS_CONTROLLER.preAppend(ObserverContextImpl.createAndPrepare(RCP_ENV),
897          new Append(TEST_ROW));
898        return null;
899      }
900    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
901
902    // preIncrement
903    verifyAllowed(new AccessTestAction() {
904      @Override
905      public Object run() throws Exception {
906        ACCESS_CONTROLLER.preIncrement(ObserverContextImpl.createAndPrepare(RCP_ENV),
907          new Increment(TEST_ROW));
908        return null;
909      }
910    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
911
912    // preScannerOpen
913    verifyAllowed(new AccessTestAction() {
914      @Override
915      public Object run() throws Exception {
916        ACCESS_CONTROLLER.preScannerOpen(ObserverContextImpl.createAndPrepare(RCP_ENV),
917          new Scan());
918        return null;
919      }
920    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
921
922    // preBulkLoadHFile
923    verifyAllowed(new AccessTestAction() {
924      @Override
925      public Object run() throws Exception {
926        List<Pair<byte[], String>> paths = Lists.newArrayList();
927        ACCESS_CONTROLLER.preBulkLoadHFile(ObserverContextImpl.createAndPrepare(RCP_ENV),
928          paths);
929        return null;
930      }
931    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
932
933  }
934
935  @Test
936  public void testPassiveCellPermissions() throws Exception {
937    final Configuration conf = TEST_UTIL.getConfiguration();
938
939    // store two sets of values, one store with a cell level ACL, and one without
940    verifyAllowed(new AccessTestAction() {
941      @Override
942      public Object run() throws Exception {
943        try(Connection connection = ConnectionFactory.createConnection(conf);
944            Table t = connection.getTable(TEST_TABLE.getTableName())) {
945          Put p;
946          // with ro ACL
947          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q1, ZERO);
948          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ));
949          t.put(p);
950          // with rw ACL
951          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q2, ZERO);
952          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ, Action.WRITE));
953          t.put(p);
954          // no ACL
955          p = new Put(TEST_ROW)
956              .addColumn(TEST_FAMILY, TEST_Q3, ZERO)
957              .addColumn(TEST_FAMILY, TEST_Q4, ZERO);
958          t.put(p);
959        }
960        return null;
961      }
962    }, USER_OWNER);
963
964    // check that a scan over the test data returns the expected number of KVs
965
966    final List<Cell> scanResults = Lists.newArrayList();
967
968    AccessTestAction scanAction = new AccessTestAction() {
969      @Override
970      public List<Cell> run() throws Exception {
971        Scan scan = new Scan();
972        scan.setStartRow(TEST_ROW);
973        scan.setStopRow(Bytes.add(TEST_ROW, new byte[]{ 0 } ));
974        scan.addFamily(TEST_FAMILY);
975        Connection connection = ConnectionFactory.createConnection(conf);
976        Table t = connection.getTable(TEST_TABLE.getTableName());
977        try {
978          ResultScanner scanner = t.getScanner(scan);
979          Result result = null;
980          do {
981            result = scanner.next();
982            if (result != null) {
983              scanResults.addAll(result.listCells());
984            }
985          } while (result != null);
986        } finally {
987          t.close();
988          connection.close();
989        }
990        return scanResults;
991      }
992    };
993
994    // owner will see all values
995    scanResults.clear();
996    verifyAllowed(scanAction, USER_OWNER);
997    assertEquals(4, scanResults.size());
998
999    // other user will also see 4 values
1000    // if cell filtering was active, we would only see 2 values
1001    scanResults.clear();
1002    verifyAllowed(scanAction, USER_NONE);
1003    assertEquals(4, scanResults.size());
1004  }
1005
1006}