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.HBaseTestingUtil;
029import org.apache.hadoop.hbase.HConstants;
030import org.apache.hadoop.hbase.NamespaceDescriptor;
031import org.apache.hadoop.hbase.ServerName;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.TableNameTestRule;
034import org.apache.hadoop.hbase.TableNotFoundException;
035import org.apache.hadoop.hbase.client.Append;
036import org.apache.hadoop.hbase.client.BalanceRequest;
037import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
038import org.apache.hadoop.hbase.client.Connection;
039import org.apache.hadoop.hbase.client.ConnectionFactory;
040import org.apache.hadoop.hbase.client.Delete;
041import org.apache.hadoop.hbase.client.Durability;
042import org.apache.hadoop.hbase.client.Get;
043import org.apache.hadoop.hbase.client.Increment;
044import org.apache.hadoop.hbase.client.Put;
045import org.apache.hadoop.hbase.client.RegionInfo;
046import org.apache.hadoop.hbase.client.RegionInfoBuilder;
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.client.TableDescriptorBuilder;
054import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
055import org.apache.hadoop.hbase.coprocessor.ObserverContextImpl;
056import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
057import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
058import org.apache.hadoop.hbase.filter.BinaryComparator;
059import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
060import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker;
061import org.apache.hadoop.hbase.regionserver.HRegion;
062import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
063import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
064import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
065import org.apache.hadoop.hbase.security.User;
066import org.apache.hadoop.hbase.security.access.Permission.Action;
067import org.apache.hadoop.hbase.testclassification.LargeTests;
068import org.apache.hadoop.hbase.testclassification.SecurityTests;
069import org.apache.hadoop.hbase.util.Bytes;
070import org.apache.hadoop.hbase.util.Pair;
071import org.apache.hadoop.hbase.wal.WALEdit;
072import org.junit.After;
073import org.junit.AfterClass;
074import org.junit.Before;
075import org.junit.BeforeClass;
076import org.junit.ClassRule;
077import org.junit.Rule;
078import org.junit.Test;
079import org.junit.experimental.categories.Category;
080import org.slf4j.Logger;
081import org.slf4j.LoggerFactory;
082
083import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
084
085@Category({ SecurityTests.class, LargeTests.class })
086public class TestWithDisabledAuthorization extends SecureTestUtil {
087
088  @ClassRule
089  public static final HBaseClassTestRule CLASS_RULE =
090    HBaseClassTestRule.forClass(TestWithDisabledAuthorization.class);
091
092  private static final Logger LOG = LoggerFactory.getLogger(TestWithDisabledAuthorization.class);
093  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
094
095  private static final byte[] TEST_FAMILY = Bytes.toBytes("f1");
096  private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
097  private static final byte[] TEST_ROW = Bytes.toBytes("testrow");
098  private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
099  private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
100  private static final byte[] TEST_Q3 = Bytes.toBytes("q3");
101  private static final byte[] TEST_Q4 = Bytes.toBytes("q4");
102  private static final byte[] ZERO = Bytes.toBytes(0L);
103
104  private static MasterCoprocessorEnvironment CP_ENV;
105  private static AccessController ACCESS_CONTROLLER;
106  private static RegionServerCoprocessorEnvironment RSCP_ENV;
107  private RegionCoprocessorEnvironment RCP_ENV;
108
109  @Rule
110  public TableNameTestRule testTable = new TableNameTestRule();
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    // Up the handlers; this test needs more than usual.
135    TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
136    // Enable security
137    enableSecurity(conf);
138    // We expect 0.98 cell ACL semantics
139    conf.setBoolean(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, false);
140    // Enable EXEC permission checking
141    conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true);
142    // Verify enableSecurity sets up what we require
143    verifyConfiguration(conf);
144
145    // Now, DISABLE only active authorization
146    conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
147
148    // Start the minicluster
149    TEST_UTIL.startMiniCluster();
150    MasterCoprocessorHost cpHost =
151      TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
152    cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
153    ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(AccessController.class.getName());
154    CP_ENV = cpHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf);
155    RegionServerCoprocessorHost rsHost =
156      TEST_UTIL.getMiniHBaseCluster().getRegionServer(0).getRegionServerCoprocessorHost();
157    RSCP_ENV = rsHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf);
158
159    // Wait for the ACL table to become available
160    TEST_UTIL.waitUntilAllRegionsAssigned(PermissionStorage.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    // Grant table creation permission to USER_OWNER
173    grantGlobal(TEST_UTIL, USER_OWNER.getShortName(), Action.CREATE);
174  }
175
176  @AfterClass
177  public static void tearDownAfterClass() throws Exception {
178    TEST_UTIL.shutdownMiniCluster();
179  }
180
181  @Before
182  public void setUp() throws Exception {
183    // Create the test table (owner added to the _acl_ table)
184    TableDescriptor tableDescriptor =
185      TableDescriptorBuilder.newBuilder(testTable.getTableName())
186        .setColumnFamily(
187          ColumnFamilyDescriptorBuilder.newBuilder(TEST_FAMILY).setMaxVersions(100).build())
188        .build();
189    createTable(TEST_UTIL, USER_OWNER, tableDescriptor, new byte[][] { Bytes.toBytes("s") });
190    TEST_UTIL.waitUntilAllRegionsAssigned(testTable.getTableName());
191
192    HRegion region = TEST_UTIL.getHBaseCluster().getRegions(testTable.getTableName()).get(0);
193    RegionCoprocessorHost rcpHost = region.getCoprocessorHost();
194    RCP_ENV = rcpHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1,
195      TEST_UTIL.getConfiguration());
196
197    // Set up initial grants
198
199    grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(), Permission.Action.ADMIN,
200      Permission.Action.CREATE, Permission.Action.READ, Permission.Action.WRITE);
201
202    grantOnTable(TEST_UTIL, USER_RW.getShortName(), testTable.getTableName(), TEST_FAMILY, null,
203      Permission.Action.READ, Permission.Action.WRITE);
204
205    // USER_CREATE is USER_RW plus CREATE permissions
206    grantOnTable(TEST_UTIL, USER_CREATE.getShortName(), testTable.getTableName(), null, null,
207      Permission.Action.CREATE, Permission.Action.READ, Permission.Action.WRITE);
208
209    grantOnTable(TEST_UTIL, USER_RO.getShortName(), testTable.getTableName(), TEST_FAMILY, null,
210      Permission.Action.READ);
211
212    grantOnTable(TEST_UTIL, USER_QUAL.getShortName(), testTable.getTableName(), TEST_FAMILY,
213      TEST_Q1, Permission.Action.READ, Permission.Action.WRITE);
214
215    assertEquals(5, PermissionStorage
216      .getTablePermissions(TEST_UTIL.getConfiguration(), testTable.getTableName()).size());
217  }
218
219  @After
220  public void tearDown() throws Exception {
221    // Clean the _acl_ table
222    try {
223      deleteTable(TEST_UTIL, testTable.getTableName());
224    } catch (TableNotFoundException ex) {
225      // Test deleted the table, no problem
226      LOG.info("Test deleted table " + testTable.getTableName());
227    }
228    // Verify all table/namespace permissions are erased
229    assertEquals(0, PermissionStorage
230      .getTablePermissions(TEST_UTIL.getConfiguration(), testTable.getTableName()).size());
231    assertEquals(0, PermissionStorage.getNamespacePermissions(TEST_UTIL.getConfiguration(),
232      testTable.getTableName().getNamespaceAsString()).size());
233  }
234
235  @Test
236  public void testCheckPermissions() throws Exception {
237
238    AccessTestAction checkGlobalAdmin = new AccessTestAction() {
239      @Override
240      public Void run() throws Exception {
241        checkGlobalPerms(TEST_UTIL, Permission.Action.ADMIN);
242        return null;
243      }
244    };
245
246    verifyAllowed(checkGlobalAdmin, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
247      USER_RO, USER_QUAL, USER_NONE);
248
249    AccessTestAction checkGlobalRead = new AccessTestAction() {
250      @Override
251      public Void run() throws Exception {
252        checkGlobalPerms(TEST_UTIL, Permission.Action.READ);
253        return null;
254      }
255    };
256
257    verifyAllowed(checkGlobalRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
258      USER_QUAL, USER_NONE);
259
260    AccessTestAction checkGlobalReadWrite = new AccessTestAction() {
261      @Override
262      public Void run() throws Exception {
263        checkGlobalPerms(TEST_UTIL, Permission.Action.READ, Permission.Action.WRITE);
264        return null;
265      }
266    };
267
268    verifyAllowed(checkGlobalReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
269      USER_RO, USER_QUAL, USER_NONE);
270
271    AccessTestAction checkTableAdmin = new AccessTestAction() {
272      @Override
273      public Void run() throws Exception {
274        checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null, Permission.Action.ADMIN);
275        return null;
276      }
277    };
278
279    verifyAllowed(checkTableAdmin, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
280      USER_QUAL, USER_NONE);
281
282    AccessTestAction checkTableCreate = new AccessTestAction() {
283      @Override
284      public Void run() throws Exception {
285        checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null, Permission.Action.CREATE);
286        return null;
287      }
288    };
289
290    verifyAllowed(checkTableCreate, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
291      USER_RO, USER_QUAL, USER_NONE);
292
293    AccessTestAction checkTableRead = new AccessTestAction() {
294      @Override
295      public Void run() throws Exception {
296        checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null, Permission.Action.READ);
297        return null;
298      }
299    };
300
301    verifyAllowed(checkTableRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
302      USER_QUAL, USER_NONE);
303
304    AccessTestAction checkTableReadWrite = new AccessTestAction() {
305      @Override
306      public Void run() throws Exception {
307        checkTablePerms(TEST_UTIL, testTable.getTableName(), null, null, Permission.Action.READ,
308          Permission.Action.WRITE);
309        return null;
310      }
311    };
312
313    verifyAllowed(checkTableReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
314      USER_RO, USER_QUAL, USER_NONE);
315
316    AccessTestAction checkColumnRead = new AccessTestAction() {
317      @Override
318      public Void run() throws Exception {
319        checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
320          Permission.Action.READ);
321        return null;
322      }
323    };
324
325    verifyAllowed(checkColumnRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
326      USER_QUAL, USER_NONE);
327
328    AccessTestAction checkColumnReadWrite = new AccessTestAction() {
329      @Override
330      public Void run() throws Exception {
331        checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
332          Permission.Action.READ, Permission.Action.WRITE);
333        return null;
334      }
335    };
336
337    verifyAllowed(checkColumnReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
338      USER_RO, USER_QUAL, USER_NONE);
339
340    AccessTestAction checkQualifierRead = new AccessTestAction() {
341      @Override
342      public Void run() throws Exception {
343        checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, TEST_Q1,
344          Permission.Action.READ);
345        return null;
346      }
347    };
348
349    verifyAllowed(checkQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
350      USER_RO, USER_QUAL, USER_NONE);
351
352    AccessTestAction checkQualifierReadWrite = new AccessTestAction() {
353      @Override
354      public Void run() throws Exception {
355        checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, TEST_Q1,
356          Permission.Action.READ, Permission.Action.WRITE);
357        return null;
358      }
359    };
360
361    verifyAllowed(checkQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
362      USER_QUAL, USER_RO, USER_NONE);
363
364    AccessTestAction checkMultiQualifierRead = new AccessTestAction() {
365      @Override
366      public Void run() throws Exception {
367        checkTablePerms(TEST_UTIL,
368          new Permission[] {
369            Permission.newBuilder(testTable.getTableName()).withFamily(TEST_FAMILY)
370              .withQualifier(TEST_Q1).withActions(Action.READ).build(),
371            Permission.newBuilder(testTable.getTableName()).withFamily(TEST_FAMILY)
372              .withQualifier(TEST_Q2).withActions(Action.READ).build() });
373        return null;
374      }
375    };
376
377    verifyAllowed(checkMultiQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
378      USER_RO, USER_QUAL, USER_NONE);
379
380    AccessTestAction checkMultiQualifierReadWrite = new AccessTestAction() {
381      @Override
382      public Void run() throws Exception {
383        checkTablePerms(TEST_UTIL,
384          new Permission[] {
385            Permission.newBuilder(testTable.getTableName()).withFamily(TEST_FAMILY)
386              .withQualifier(TEST_Q1).withActions(Permission.Action.READ, Permission.Action.WRITE)
387              .build(),
388            Permission.newBuilder(testTable.getTableName()).withFamily(TEST_FAMILY)
389              .withQualifier(TEST_Q2).withActions(Permission.Action.READ, Permission.Action.WRITE)
390              .build() });
391        return null;
392      }
393    };
394
395    verifyAllowed(checkMultiQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
396      USER_RW, USER_RO, USER_QUAL, USER_NONE);
397  }
398
399  /** Test grants and revocations with authorization disabled */
400  @Test
401  public void testPassiveGrantRevoke() throws Exception {
402
403    // Add a test user
404
405    User tblUser =
406      User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser", new String[0]);
407
408    // If we check now, the test user have permissions because authorization is disabled
409
410    AccessTestAction checkTableRead = new AccessTestAction() {
411      @Override
412      public Void run() throws Exception {
413        checkTablePerms(TEST_UTIL, testTable.getTableName(), TEST_FAMILY, null,
414          Permission.Action.READ);
415        return null;
416      }
417    };
418
419    verifyAllowed(tblUser, checkTableRead);
420
421    // An actual read won't be denied
422
423    AccessTestAction tableRead = new AccessTestAction() {
424      @Override
425      public Void run() throws Exception {
426        try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
427          Table t = conn.getTable(testTable.getTableName())) {
428          t.get(new Get(TEST_ROW).addFamily(TEST_FAMILY));
429        }
430        return null;
431      }
432    };
433
434    verifyAllowed(tblUser, tableRead);
435
436    // Grant read perms to the test user
437
438    grantOnTable(TEST_UTIL, tblUser.getShortName(), testTable.getTableName(), TEST_FAMILY, null,
439      Permission.Action.READ);
440
441    // Now both the permission check and actual op will succeed
442
443    verifyAllowed(tblUser, checkTableRead);
444    verifyAllowed(tblUser, tableRead);
445
446    // Revoke read perms from the test user
447
448    revokeFromTable(TEST_UTIL, tblUser.getShortName(), testTable.getTableName(), TEST_FAMILY, null,
449      Permission.Action.READ);
450
451    // Now the permission check will indicate revocation but the actual op will still succeed
452
453    verifyAllowed(tblUser, checkTableRead);
454    verifyAllowed(tblUser, tableRead);
455  }
456
457  /** Test master observer */
458  @Test
459  public void testPassiveMasterOperations() throws Exception {
460
461    // preCreateTable
462    verifyAllowed(new AccessTestAction() {
463      @Override
464      public Object run() throws Exception {
465        TableDescriptor tableDescriptor =
466          TableDescriptorBuilder.newBuilder(testTable.getTableName())
467            .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build();
468        ACCESS_CONTROLLER.preCreateTable(ObserverContextImpl.createAndPrepare(CP_ENV),
469          tableDescriptor, null);
470        return null;
471      }
472    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
473
474    // preModifyTable
475    verifyAllowed(new AccessTestAction() {
476      @Override
477      public Object run() throws Exception {
478        TableDescriptor tableDescriptor =
479          TableDescriptorBuilder.newBuilder(testTable.getTableName())
480            .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY))
481            .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY2)).build();
482        ACCESS_CONTROLLER.preModifyTable(ObserverContextImpl.createAndPrepare(CP_ENV),
483          testTable.getTableName(), null, // not needed by AccessController
484          tableDescriptor);
485        return null;
486      }
487    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
488
489    // preDeleteTable
490    verifyAllowed(new AccessTestAction() {
491      @Override
492      public Object run() throws Exception {
493        ACCESS_CONTROLLER.preDeleteTable(ObserverContextImpl.createAndPrepare(CP_ENV),
494          testTable.getTableName());
495        return null;
496      }
497    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
498
499    // preTruncateTable
500    verifyAllowed(new AccessTestAction() {
501      @Override
502      public Object run() throws Exception {
503        ACCESS_CONTROLLER.preTruncateTable(ObserverContextImpl.createAndPrepare(CP_ENV),
504          testTable.getTableName());
505        return null;
506      }
507    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
508
509    // preEnableTable
510    verifyAllowed(new AccessTestAction() {
511      @Override
512      public Object run() throws Exception {
513        ACCESS_CONTROLLER.preEnableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
514          testTable.getTableName());
515        return null;
516      }
517    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
518
519    // preDisableTable
520    verifyAllowed(new AccessTestAction() {
521      @Override
522      public Object run() throws Exception {
523        ACCESS_CONTROLLER.preDisableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
524          testTable.getTableName());
525        return null;
526      }
527    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
528
529    // preMove
530    verifyAllowed(new AccessTestAction() {
531      @Override
532      public Object run() throws Exception {
533        RegionInfo region = RegionInfoBuilder.newBuilder(testTable.getTableName()).build();
534        ServerName srcServer = ServerName.valueOf("1.1.1.1", 1, 0);
535        ServerName destServer = ServerName.valueOf("2.2.2.2", 2, 0);
536        ACCESS_CONTROLLER.preMove(ObserverContextImpl.createAndPrepare(CP_ENV), region, srcServer,
537          destServer);
538        return null;
539      }
540    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
541
542    // preAssign
543    verifyAllowed(new AccessTestAction() {
544      @Override
545      public Object run() throws Exception {
546        RegionInfo region = RegionInfoBuilder.newBuilder(testTable.getTableName()).build();
547        ACCESS_CONTROLLER.preAssign(ObserverContextImpl.createAndPrepare(CP_ENV), region);
548        return null;
549      }
550    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
551
552    // preUnassign
553    verifyAllowed(new AccessTestAction() {
554      @Override
555      public Object run() throws Exception {
556        RegionInfo region = RegionInfoBuilder.newBuilder(testTable.getTableName()).build();
557        ACCESS_CONTROLLER.preUnassign(ObserverContextImpl.createAndPrepare(CP_ENV), region);
558        return null;
559      }
560    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
561
562    // preBalance
563    verifyAllowed(new AccessTestAction() {
564      @Override
565      public Object run() throws Exception {
566        ACCESS_CONTROLLER.preBalance(ObserverContextImpl.createAndPrepare(CP_ENV),
567          BalanceRequest.defaultInstance());
568        return null;
569      }
570    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
571
572    // preBalanceSwitch
573    verifyAllowed(new AccessTestAction() {
574      @Override
575      public Object run() throws Exception {
576        ACCESS_CONTROLLER.preBalanceSwitch(ObserverContextImpl.createAndPrepare(CP_ENV), true);
577        return null;
578      }
579    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
580
581    // preSnapshot
582    verifyAllowed(new AccessTestAction() {
583      @Override
584      public Object run() throws Exception {
585        SnapshotDescription snapshot = new SnapshotDescription("foo");
586        TableDescriptor htd = TableDescriptorBuilder.newBuilder(testTable.getTableName()).build();
587        ACCESS_CONTROLLER.preSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot, htd);
588        return null;
589      }
590    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
591
592    // preListSnapshot
593    verifyAllowed(new AccessTestAction() {
594      @Override
595      public Object run() throws Exception {
596        SnapshotDescription snapshot = new SnapshotDescription("foo");
597        ACCESS_CONTROLLER.preListSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot);
598        return null;
599      }
600    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
601
602    // preCloneSnapshot
603    verifyAllowed(new AccessTestAction() {
604      @Override
605      public Object run() throws Exception {
606        SnapshotDescription snapshot = new SnapshotDescription("foo");
607        TableDescriptor htd = TableDescriptorBuilder.newBuilder(testTable.getTableName()).build();
608        ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot,
609          htd);
610        return null;
611      }
612    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
613
614    // preRestoreSnapshot
615    verifyAllowed(new AccessTestAction() {
616      @Override
617      public Object run() throws Exception {
618        SnapshotDescription snapshot = new SnapshotDescription("foo");
619        TableDescriptor htd = TableDescriptorBuilder.newBuilder(testTable.getTableName()).build();
620        ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot,
621          htd);
622        return null;
623      }
624    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
625
626    // preDeleteSnapshot
627    verifyAllowed(new AccessTestAction() {
628      @Override
629      public Object run() throws Exception {
630        SnapshotDescription snapshot = new SnapshotDescription("foo");
631        ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), snapshot);
632        return null;
633      }
634    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
635
636    // preGetTableDescriptors
637    verifyAllowed(new AccessTestAction() {
638      @Override
639      public Object run() throws Exception {
640        List<TableName> tableNamesList = Lists.newArrayList();
641        tableNamesList.add(testTable.getTableName());
642        List<TableDescriptor> descriptors = Lists.newArrayList();
643        ACCESS_CONTROLLER.preGetTableDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
644          tableNamesList, descriptors, ".+");
645        return null;
646      }
647    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
648
649    // preGetTableNames
650    verifyAllowed(new AccessTestAction() {
651      @Override
652      public Object run() throws Exception {
653        List<TableDescriptor> descriptors = Lists.newArrayList();
654        ACCESS_CONTROLLER.preGetTableNames(ObserverContextImpl.createAndPrepare(CP_ENV),
655          descriptors, ".+");
656        return null;
657      }
658    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
659
660    // preCreateNamespace
661    verifyAllowed(new AccessTestAction() {
662      @Override
663      public Object run() throws Exception {
664        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
665        ACCESS_CONTROLLER.preCreateNamespace(ObserverContextImpl.createAndPrepare(CP_ENV), ns);
666        return null;
667      }
668    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
669
670    // preDeleteNamespace
671    verifyAllowed(new AccessTestAction() {
672      @Override
673      public Object run() throws Exception {
674        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContextImpl.createAndPrepare(CP_ENV), "test");
675        return null;
676      }
677    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
678
679    // preModifyNamespace
680    verifyAllowed(new AccessTestAction() {
681      @Override
682      public Object run() throws Exception {
683        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
684        ACCESS_CONTROLLER.preModifyNamespace(ObserverContextImpl.createAndPrepare(CP_ENV), null, // not
685                                                                                                 // needed
686                                                                                                 // by
687                                                                                                 // AccessController
688          ns);
689        return null;
690      }
691    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
692
693    // preGetNamespaceDescriptor
694    verifyAllowed(new AccessTestAction() {
695      @Override
696      public Object run() throws Exception {
697        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContextImpl.createAndPrepare(CP_ENV),
698          "test");
699        return null;
700      }
701    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
702
703    // preListNamespaceDescriptors
704    verifyAllowed(new AccessTestAction() {
705      @Override
706      public Object run() throws Exception {
707        List<NamespaceDescriptor> descriptors = Lists.newArrayList();
708        ACCESS_CONTROLLER.preListNamespaceDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
709          descriptors);
710        return null;
711      }
712    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
713
714    // preSplit
715    verifyAllowed(new AccessTestAction() {
716      @Override
717      public Object run() throws Exception {
718        ACCESS_CONTROLLER.preSplitRegion(ObserverContextImpl.createAndPrepare(CP_ENV),
719          testTable.getTableName(), Bytes.toBytes("ss"));
720        return null;
721      }
722    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
723
724    // preSetUserQuota
725    verifyAllowed(new AccessTestAction() {
726      @Override
727      public Object run() throws Exception {
728        ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV), "testuser",
729          null);
730        return null;
731      }
732    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
733
734    // preSetTableQuota
735    verifyAllowed(new AccessTestAction() {
736      @Override
737      public Object run() throws Exception {
738        ACCESS_CONTROLLER.preSetTableQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
739          testTable.getTableName(), null);
740        return null;
741      }
742    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
743
744    // preSetNamespaceQuota
745    verifyAllowed(new AccessTestAction() {
746      @Override
747      public Object run() throws Exception {
748        ACCESS_CONTROLLER.preSetNamespaceQuota(ObserverContextImpl.createAndPrepare(CP_ENV), "test",
749          null);
750        return null;
751      }
752    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
753
754  }
755
756  /** Test region server observer */
757  @Test
758  public void testPassiveRegionServerOperations() throws Exception {
759    // preStopRegionServer
760    verifyAllowed(new AccessTestAction() {
761      @Override
762      public Object run() throws Exception {
763        ACCESS_CONTROLLER.preStopRegionServer(ObserverContextImpl.createAndPrepare(RSCP_ENV));
764        return null;
765      }
766    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
767
768    // preRollWALWriterRequest
769    verifyAllowed(new AccessTestAction() {
770      @Override
771      public Object run() throws Exception {
772        ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContextImpl.createAndPrepare(RSCP_ENV));
773        return null;
774      }
775    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
776
777  }
778
779  /** Test region observer */
780  @Test
781  public void testPassiveRegionOperations() throws Exception {
782
783    // preOpen
784    verifyAllowed(new AccessTestAction() {
785      @Override
786      public Object run() throws Exception {
787        ACCESS_CONTROLLER.preOpen(ObserverContextImpl.createAndPrepare(RCP_ENV));
788        return null;
789      }
790    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
791
792    // preFlush
793    verifyAllowed(new AccessTestAction() {
794      @Override
795      public Object run() throws Exception {
796        ACCESS_CONTROLLER.preFlush(ObserverContextImpl.createAndPrepare(RCP_ENV),
797          FlushLifeCycleTracker.DUMMY);
798        return null;
799      }
800    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
801
802    // preGetOp
803    verifyAllowed(new AccessTestAction() {
804      @Override
805      public Object run() throws Exception {
806        List<Cell> cells = Lists.newArrayList();
807        ACCESS_CONTROLLER.preGetOp(ObserverContextImpl.createAndPrepare(RCP_ENV), new Get(TEST_ROW),
808          cells);
809        return null;
810      }
811    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
812
813    // preExists
814    verifyAllowed(new AccessTestAction() {
815      @Override
816      public Object run() throws Exception {
817        ACCESS_CONTROLLER.preExists(ObserverContextImpl.createAndPrepare(RCP_ENV),
818          new Get(TEST_ROW), true);
819        return null;
820      }
821    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
822
823    // prePut
824    verifyAllowed(new AccessTestAction() {
825      @Override
826      public Object run() throws Exception {
827        ACCESS_CONTROLLER.prePut(ObserverContextImpl.createAndPrepare(RCP_ENV), new Put(TEST_ROW),
828          new WALEdit(), Durability.USE_DEFAULT);
829        return null;
830      }
831    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
832
833    // preDelete
834    verifyAllowed(new AccessTestAction() {
835      @Override
836      public Object run() throws Exception {
837        ACCESS_CONTROLLER.preDelete(ObserverContextImpl.createAndPrepare(RCP_ENV),
838          new Delete(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
839        return null;
840      }
841    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
842
843    // preBatchMutate
844    verifyAllowed(new AccessTestAction() {
845      @Override
846      public Object run() throws Exception {
847        ACCESS_CONTROLLER.preBatchMutate(ObserverContextImpl.createAndPrepare(RCP_ENV),
848          new MiniBatchOperationInProgress<>(null, null, null, 0, 0, 0));
849        return null;
850      }
851    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
852
853    // preCheckAndPut
854    verifyAllowed(new AccessTestAction() {
855      @Override
856      public Object run() throws Exception {
857        ACCESS_CONTROLLER.preCheckAndPut(ObserverContextImpl.createAndPrepare(RCP_ENV), TEST_ROW,
858          TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("foo")),
859          new Put(TEST_ROW), true);
860        return null;
861      }
862    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
863
864    // preCheckAndDelete
865    verifyAllowed(new AccessTestAction() {
866      @Override
867      public Object run() throws Exception {
868        ACCESS_CONTROLLER.preCheckAndDelete(ObserverContextImpl.createAndPrepare(RCP_ENV), TEST_ROW,
869          TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("foo")),
870          new Delete(TEST_ROW), true);
871        return null;
872      }
873    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
874
875    // preAppend
876    verifyAllowed(new AccessTestAction() {
877      @Override
878      public Object run() throws Exception {
879        ACCESS_CONTROLLER.preAppend(ObserverContextImpl.createAndPrepare(RCP_ENV),
880          new Append(TEST_ROW));
881        return null;
882      }
883    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
884
885    // preIncrement
886    verifyAllowed(new AccessTestAction() {
887      @Override
888      public Object run() throws Exception {
889        ACCESS_CONTROLLER.preIncrement(ObserverContextImpl.createAndPrepare(RCP_ENV),
890          new Increment(TEST_ROW));
891        return null;
892      }
893    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
894
895    // preScannerOpen
896    verifyAllowed(new AccessTestAction() {
897      @Override
898      public Object run() throws Exception {
899        ACCESS_CONTROLLER.preScannerOpen(ObserverContextImpl.createAndPrepare(RCP_ENV), new Scan());
900        return null;
901      }
902    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
903
904    // preBulkLoadHFile
905    verifyAllowed(new AccessTestAction() {
906      @Override
907      public Object run() throws Exception {
908        List<Pair<byte[], String>> paths = Lists.newArrayList();
909        ACCESS_CONTROLLER.preBulkLoadHFile(ObserverContextImpl.createAndPrepare(RCP_ENV), paths);
910        return null;
911      }
912    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
913
914  }
915
916  @Test
917  public void testPassiveCellPermissions() throws Exception {
918    final Configuration conf = TEST_UTIL.getConfiguration();
919
920    // store two sets of values, one store with a cell level ACL, and one without
921    verifyAllowed(new AccessTestAction() {
922      @Override
923      public Object run() throws Exception {
924        try (Connection connection = ConnectionFactory.createConnection(conf);
925          Table t = connection.getTable(testTable.getTableName())) {
926          Put p;
927          // with ro ACL
928          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q1, ZERO);
929          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ));
930          t.put(p);
931          // with rw ACL
932          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q2, ZERO);
933          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ, Action.WRITE));
934          t.put(p);
935          // no ACL
936          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q3, ZERO).addColumn(TEST_FAMILY,
937            TEST_Q4, ZERO);
938          t.put(p);
939        }
940        return null;
941      }
942    }, USER_OWNER);
943
944    // check that a scan over the test data returns the expected number of KVs
945
946    final List<Cell> scanResults = Lists.newArrayList();
947
948    AccessTestAction scanAction = new AccessTestAction() {
949      @Override
950      public List<Cell> run() throws Exception {
951        Scan scan = new Scan();
952        scan.withStartRow(TEST_ROW);
953        scan.withStopRow(Bytes.add(TEST_ROW, new byte[] { 0 }));
954        scan.addFamily(TEST_FAMILY);
955        Connection connection = ConnectionFactory.createConnection(conf);
956        Table t = connection.getTable(testTable.getTableName());
957        try {
958          ResultScanner scanner = t.getScanner(scan);
959          Result result = null;
960          do {
961            result = scanner.next();
962            if (result != null) {
963              scanResults.addAll(result.listCells());
964            }
965          } while (result != null);
966        } finally {
967          t.close();
968          connection.close();
969        }
970        return scanResults;
971      }
972    };
973
974    // owner will see all values
975    scanResults.clear();
976    verifyAllowed(scanAction, USER_OWNER);
977    assertEquals(4, scanResults.size());
978
979    // other user will also see 4 values
980    // if cell filtering was active, we would only see 2 values
981    scanResults.clear();
982    verifyAllowed(scanAction, USER_NONE);
983    assertEquals(4, scanResults.size());
984  }
985
986}