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