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