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(PermissionStorage.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, PermissionStorage
223        .getTablePermissions(TEST_UTIL.getConfiguration(), 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, PermissionStorage
237        .getTablePermissions(TEST_UTIL.getConfiguration(), TEST_TABLE.getTableName()).size());
238    assertEquals(0, PermissionStorage.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(),
492          null,  // not needed by AccessController
493          htd);
494        return null;
495      }
496    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
497
498    // preDeleteTable
499    verifyAllowed(new AccessTestAction() {
500      @Override
501      public Object run() throws Exception {
502        ACCESS_CONTROLLER.preDeleteTable(ObserverContextImpl.createAndPrepare(CP_ENV),
503          TEST_TABLE.getTableName());
504        return null;
505      }
506    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
507
508    // preTruncateTable
509    verifyAllowed(new AccessTestAction() {
510      @Override
511      public Object run() throws Exception {
512        ACCESS_CONTROLLER.preTruncateTable(ObserverContextImpl.createAndPrepare(CP_ENV),
513          TEST_TABLE.getTableName());
514        return null;
515      }
516    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
517
518    // preEnableTable
519    verifyAllowed(new AccessTestAction() {
520      @Override
521      public Object run() throws Exception {
522        ACCESS_CONTROLLER.preEnableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
523          TEST_TABLE.getTableName());
524        return null;
525      }
526    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
527
528    // preDisableTable
529    verifyAllowed(new AccessTestAction() {
530      @Override
531      public Object run() throws Exception {
532        ACCESS_CONTROLLER.preDisableTable(ObserverContextImpl.createAndPrepare(CP_ENV),
533          TEST_TABLE.getTableName());
534        return null;
535      }
536    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
537
538    // preMove
539    verifyAllowed(new AccessTestAction() {
540      @Override
541      public Object run() throws Exception {
542        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
543        ServerName srcServer = ServerName.valueOf("1.1.1.1", 1, 0);
544        ServerName destServer = ServerName.valueOf("2.2.2.2", 2, 0);
545        ACCESS_CONTROLLER.preMove(ObserverContextImpl.createAndPrepare(CP_ENV), region,
546          srcServer, destServer);
547        return null;
548      }
549    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
550
551    // preAssign
552    verifyAllowed(new AccessTestAction() {
553      @Override
554      public Object run() throws Exception {
555        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
556        ACCESS_CONTROLLER.preAssign(ObserverContextImpl.createAndPrepare(CP_ENV), region);
557        return null;
558      }
559    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
560
561    // preUnassign
562    verifyAllowed(new AccessTestAction() {
563      @Override
564      public Object run() throws Exception {
565        HRegionInfo region = new HRegionInfo(TEST_TABLE.getTableName());
566        ACCESS_CONTROLLER.preUnassign(ObserverContextImpl.createAndPrepare(CP_ENV), region,
567          true);
568        return null;
569      }
570    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
571
572    // preBalance
573    verifyAllowed(new AccessTestAction() {
574      @Override
575      public Object run() throws Exception {
576        ACCESS_CONTROLLER.preBalance(ObserverContextImpl.createAndPrepare(CP_ENV));
577        return null;
578      }
579    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
580
581    // preBalanceSwitch
582    verifyAllowed(new AccessTestAction() {
583      @Override
584      public Object run() throws Exception {
585        ACCESS_CONTROLLER.preBalanceSwitch(ObserverContextImpl.createAndPrepare(CP_ENV),
586          true);
587        return null;
588      }
589    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
590
591    // preSnapshot
592    verifyAllowed(new AccessTestAction() {
593      @Override
594      public Object run() throws Exception {
595        SnapshotDescription snapshot = new SnapshotDescription("foo");
596        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
597        ACCESS_CONTROLLER.preSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
598          snapshot, htd);
599        return null;
600      }
601    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
602
603    // preListSnapshot
604    verifyAllowed(new AccessTestAction() {
605      @Override
606      public Object run() throws Exception {
607        SnapshotDescription snapshot = new SnapshotDescription("foo");
608        ACCESS_CONTROLLER.preListSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
609          snapshot);
610        return null;
611      }
612    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
613
614    // preCloneSnapshot
615    verifyAllowed(new AccessTestAction() {
616      @Override
617      public Object run() throws Exception {
618        SnapshotDescription snapshot = new SnapshotDescription("foo");
619        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
620        ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
621          snapshot, htd);
622        return null;
623      }
624    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
625
626    // preRestoreSnapshot
627    verifyAllowed(new AccessTestAction() {
628      @Override
629      public Object run() throws Exception {
630        SnapshotDescription snapshot = new SnapshotDescription("foo");
631        HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
632        ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
633          snapshot, htd);
634        return null;
635      }
636    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
637
638    // preDeleteSnapshot
639    verifyAllowed(new AccessTestAction() {
640      @Override
641      public Object run() throws Exception {
642        SnapshotDescription snapshot = new SnapshotDescription("foo");
643        ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV),
644          snapshot);
645        return null;
646      }
647    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
648
649    // preGetTableDescriptors
650    verifyAllowed(new AccessTestAction() {
651      @Override
652      public Object run() throws Exception {
653        List<TableName> tableNamesList = Lists.newArrayList();
654        tableNamesList.add(TEST_TABLE.getTableName());
655        List<TableDescriptor> descriptors = Lists.newArrayList();
656        ACCESS_CONTROLLER.preGetTableDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
657          tableNamesList, descriptors, ".+");
658        return null;
659      }
660    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
661
662    // preGetTableNames
663    verifyAllowed(new AccessTestAction() {
664      @Override
665      public Object run() throws Exception {
666        List<TableDescriptor> descriptors = Lists.newArrayList();
667        ACCESS_CONTROLLER.preGetTableNames(ObserverContextImpl.createAndPrepare(CP_ENV),
668          descriptors, ".+");
669        return null;
670      }
671    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
672
673    // preCreateNamespace
674    verifyAllowed(new AccessTestAction() {
675      @Override
676      public Object run() throws Exception {
677        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
678        ACCESS_CONTROLLER.preCreateNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
679          ns);
680        return null;
681      }
682    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
683
684    // preDeleteNamespace
685    verifyAllowed(new AccessTestAction() {
686      @Override
687      public Object run() throws Exception {
688        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
689          "test");
690        return null;
691      }
692    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
693
694    // preModifyNamespace
695    verifyAllowed(new AccessTestAction() {
696      @Override
697      public Object run() throws Exception {
698        NamespaceDescriptor ns = NamespaceDescriptor.create("test").build();
699        ACCESS_CONTROLLER.preModifyNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
700          null,  // not needed by AccessController
701          ns);
702        return null;
703      }
704    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
705
706    // preGetNamespaceDescriptor
707    verifyAllowed(new AccessTestAction() {
708      @Override
709      public Object run() throws Exception {
710        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContextImpl.createAndPrepare(CP_ENV),
711          "test");
712        return null;
713      }
714    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
715
716    // preListNamespaceDescriptors
717    verifyAllowed(new AccessTestAction() {
718      @Override
719      public Object run() throws Exception {
720        List<NamespaceDescriptor> descriptors = Lists.newArrayList();
721        ACCESS_CONTROLLER.preListNamespaceDescriptors(ObserverContextImpl.createAndPrepare(CP_ENV),
722          descriptors);
723        return null;
724      }
725    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
726
727    // preSplit
728    verifyAllowed(new AccessTestAction() {
729      @Override
730      public Object run() throws Exception {
731        ACCESS_CONTROLLER.preSplitRegion(
732          ObserverContextImpl.createAndPrepare(CP_ENV),
733          TEST_TABLE.getTableName(),
734          Bytes.toBytes("ss"));
735        return null;
736      }
737    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
738
739    // preSetUserQuota
740    verifyAllowed(new AccessTestAction() {
741      @Override
742      public Object run() throws Exception {
743        ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
744          "testuser", null);
745        return null;
746      }
747    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
748
749    // preSetTableQuota
750    verifyAllowed(new AccessTestAction() {
751      @Override
752      public Object run() throws Exception {
753        ACCESS_CONTROLLER.preSetTableQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
754          TEST_TABLE.getTableName(), null);
755        return null;
756      }
757    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
758
759    // preSetNamespaceQuota
760    verifyAllowed(new AccessTestAction() {
761      @Override
762      public Object run() throws Exception {
763        ACCESS_CONTROLLER.preSetNamespaceQuota(ObserverContextImpl.createAndPrepare(CP_ENV),
764          "test", null);
765        return null;
766      }
767    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
768
769  }
770
771  /** Test region server observer */
772  @Test
773  public void testPassiveRegionServerOperations() throws Exception {
774    // preStopRegionServer
775    verifyAllowed(new AccessTestAction() {
776      @Override
777      public Object run() throws Exception {
778        ACCESS_CONTROLLER.preStopRegionServer(ObserverContextImpl.createAndPrepare(RSCP_ENV));
779        return null;
780      }
781    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
782
783    // preRollWALWriterRequest
784    verifyAllowed(new AccessTestAction() {
785      @Override
786      public Object run() throws Exception {
787        ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContextImpl.createAndPrepare(RSCP_ENV));
788        return null;
789      }
790    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
791
792  }
793
794  /** Test region observer */
795  @Test
796  public void testPassiveRegionOperations() throws Exception {
797
798    // preOpen
799    verifyAllowed(new AccessTestAction() {
800      @Override
801      public Object run() throws Exception {
802        ACCESS_CONTROLLER.preOpen(ObserverContextImpl.createAndPrepare(RCP_ENV));
803        return null;
804      }
805    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
806
807    // preFlush
808    verifyAllowed(new AccessTestAction() {
809      @Override
810      public Object run() throws Exception {
811        ACCESS_CONTROLLER.preFlush(ObserverContextImpl.createAndPrepare(RCP_ENV),
812          FlushLifeCycleTracker.DUMMY);
813        return null;
814      }
815    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
816
817    // preGetOp
818    verifyAllowed(new AccessTestAction() {
819      @Override
820      public Object run() throws Exception {
821        List<Cell> cells = Lists.newArrayList();
822        ACCESS_CONTROLLER.preGetOp(ObserverContextImpl.createAndPrepare(RCP_ENV),
823          new Get(TEST_ROW), cells);
824        return null;
825      }
826    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
827
828    // preExists
829    verifyAllowed(new AccessTestAction() {
830      @Override
831      public Object run() throws Exception {
832        ACCESS_CONTROLLER.preExists(ObserverContextImpl.createAndPrepare(RCP_ENV),
833          new Get(TEST_ROW), true);
834        return null;
835      }
836    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
837
838    // prePut
839    verifyAllowed(new AccessTestAction() {
840      @Override
841      public Object run() throws Exception {
842        ACCESS_CONTROLLER.prePut(ObserverContextImpl.createAndPrepare(RCP_ENV),
843          new Put(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
844        return null;
845      }
846    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
847
848    // preDelete
849    verifyAllowed(new AccessTestAction() {
850      @Override
851      public Object run() throws Exception {
852        ACCESS_CONTROLLER.preDelete(ObserverContextImpl.createAndPrepare(RCP_ENV),
853          new Delete(TEST_ROW), new WALEdit(), Durability.USE_DEFAULT);
854        return null;
855      }
856    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
857
858    // preBatchMutate
859    verifyAllowed(new AccessTestAction() {
860      @Override
861      public Object run() throws Exception {
862        ACCESS_CONTROLLER.preBatchMutate(ObserverContextImpl.createAndPrepare(RCP_ENV),
863          new MiniBatchOperationInProgress<>(null, null, null, 0, 0, 0));
864        return null;
865      }
866    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
867
868    // preCheckAndPut
869    verifyAllowed(new AccessTestAction() {
870      @Override
871      public Object run() throws Exception {
872        ACCESS_CONTROLLER.preCheckAndPut(ObserverContextImpl.createAndPrepare(RCP_ENV),
873          TEST_ROW, TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL,
874          new BinaryComparator(Bytes.toBytes("foo")), new Put(TEST_ROW), true);
875        return null;
876      }
877    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
878
879    // preCheckAndDelete
880    verifyAllowed(new AccessTestAction() {
881      @Override
882      public Object run() throws Exception {
883        ACCESS_CONTROLLER.preCheckAndDelete(ObserverContextImpl.createAndPrepare(RCP_ENV),
884          TEST_ROW, TEST_FAMILY, TEST_Q1, CompareOperator.EQUAL,
885          new BinaryComparator(Bytes.toBytes("foo")), new Delete(TEST_ROW), true);
886        return null;
887      }
888    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
889
890    // preAppend
891    verifyAllowed(new AccessTestAction() {
892      @Override
893      public Object run() throws Exception {
894        ACCESS_CONTROLLER.preAppend(ObserverContextImpl.createAndPrepare(RCP_ENV),
895          new Append(TEST_ROW));
896        return null;
897      }
898    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
899
900    // preIncrement
901    verifyAllowed(new AccessTestAction() {
902      @Override
903      public Object run() throws Exception {
904        ACCESS_CONTROLLER.preIncrement(ObserverContextImpl.createAndPrepare(RCP_ENV),
905          new Increment(TEST_ROW));
906        return null;
907      }
908    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
909
910    // preScannerOpen
911    verifyAllowed(new AccessTestAction() {
912      @Override
913      public Object run() throws Exception {
914        ACCESS_CONTROLLER.preScannerOpen(ObserverContextImpl.createAndPrepare(RCP_ENV),
915          new Scan());
916        return null;
917      }
918    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
919
920    // preBulkLoadHFile
921    verifyAllowed(new AccessTestAction() {
922      @Override
923      public Object run() throws Exception {
924        List<Pair<byte[], String>> paths = Lists.newArrayList();
925        ACCESS_CONTROLLER.preBulkLoadHFile(ObserverContextImpl.createAndPrepare(RCP_ENV),
926          paths);
927        return null;
928      }
929    }, SUPERUSER, USER_ADMIN, USER_RW, USER_RO, USER_OWNER, USER_CREATE, USER_QUAL, USER_NONE);
930
931  }
932
933  @Test
934  public void testPassiveCellPermissions() throws Exception {
935    final Configuration conf = TEST_UTIL.getConfiguration();
936
937    // store two sets of values, one store with a cell level ACL, and one without
938    verifyAllowed(new AccessTestAction() {
939      @Override
940      public Object run() throws Exception {
941        try(Connection connection = ConnectionFactory.createConnection(conf);
942            Table t = connection.getTable(TEST_TABLE.getTableName())) {
943          Put p;
944          // with ro ACL
945          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q1, ZERO);
946          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ));
947          t.put(p);
948          // with rw ACL
949          p = new Put(TEST_ROW).addColumn(TEST_FAMILY, TEST_Q2, ZERO);
950          p.setACL(USER_NONE.getShortName(), new Permission(Action.READ, Action.WRITE));
951          t.put(p);
952          // no ACL
953          p = new Put(TEST_ROW)
954              .addColumn(TEST_FAMILY, TEST_Q3, ZERO)
955              .addColumn(TEST_FAMILY, TEST_Q4, ZERO);
956          t.put(p);
957        }
958        return null;
959      }
960    }, USER_OWNER);
961
962    // check that a scan over the test data returns the expected number of KVs
963
964    final List<Cell> scanResults = Lists.newArrayList();
965
966    AccessTestAction scanAction = new AccessTestAction() {
967      @Override
968      public List<Cell> run() throws Exception {
969        Scan scan = new Scan();
970        scan.setStartRow(TEST_ROW);
971        scan.setStopRow(Bytes.add(TEST_ROW, new byte[]{ 0 } ));
972        scan.addFamily(TEST_FAMILY);
973        Connection connection = ConnectionFactory.createConnection(conf);
974        Table t = connection.getTable(TEST_TABLE.getTableName());
975        try {
976          ResultScanner scanner = t.getScanner(scan);
977          Result result = null;
978          do {
979            result = scanner.next();
980            if (result != null) {
981              scanResults.addAll(result.listCells());
982            }
983          } while (result != null);
984        } finally {
985          t.close();
986          connection.close();
987        }
988        return scanResults;
989      }
990    };
991
992    // owner will see all values
993    scanResults.clear();
994    verifyAllowed(scanAction, USER_OWNER);
995    assertEquals(4, scanResults.size());
996
997    // other user will also see 4 values
998    // if cell filtering was active, we would only see 2 values
999    scanResults.clear();
1000    verifyAllowed(scanAction, USER_NONE);
1001    assertEquals(4, scanResults.size());
1002  }
1003
1004}