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