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.apache.hadoop.hbase.AuthUtil.toGroupEntry; 021import static org.junit.Assert.assertArrayEquals; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertFalse; 024import static org.junit.Assert.assertNotNull; 025import static org.junit.Assert.assertTrue; 026import static org.junit.Assert.fail; 027 028import com.google.protobuf.BlockingRpcChannel; 029import com.google.protobuf.RpcCallback; 030import com.google.protobuf.RpcController; 031import com.google.protobuf.Service; 032import com.google.protobuf.ServiceException; 033import java.io.IOException; 034import java.security.PrivilegedAction; 035import java.util.ArrayList; 036import java.util.Arrays; 037import java.util.Collection; 038import java.util.Collections; 039import java.util.List; 040import org.apache.hadoop.conf.Configuration; 041import org.apache.hadoop.fs.FileStatus; 042import org.apache.hadoop.fs.FileSystem; 043import org.apache.hadoop.fs.Path; 044import org.apache.hadoop.fs.permission.FsPermission; 045import org.apache.hadoop.hbase.Coprocessor; 046import org.apache.hadoop.hbase.CoprocessorEnvironment; 047import org.apache.hadoop.hbase.HBaseClassTestRule; 048import org.apache.hadoop.hbase.HBaseIOException; 049import org.apache.hadoop.hbase.HBaseTestingUtility; 050import org.apache.hadoop.hbase.HColumnDescriptor; 051import org.apache.hadoop.hbase.HConstants; 052import org.apache.hadoop.hbase.HRegionInfo; 053import org.apache.hadoop.hbase.HRegionLocation; 054import org.apache.hadoop.hbase.HTableDescriptor; 055import org.apache.hadoop.hbase.KeyValue; 056import org.apache.hadoop.hbase.MiniHBaseCluster; 057import org.apache.hadoop.hbase.NamespaceDescriptor; 058import org.apache.hadoop.hbase.ServerName; 059import org.apache.hadoop.hbase.TableName; 060import org.apache.hadoop.hbase.TableNotFoundException; 061import org.apache.hadoop.hbase.client.Admin; 062import org.apache.hadoop.hbase.client.Append; 063import org.apache.hadoop.hbase.client.Connection; 064import org.apache.hadoop.hbase.client.ConnectionFactory; 065import org.apache.hadoop.hbase.client.Delete; 066import org.apache.hadoop.hbase.client.Get; 067import org.apache.hadoop.hbase.client.Increment; 068import org.apache.hadoop.hbase.client.MasterSwitchType; 069import org.apache.hadoop.hbase.client.Put; 070import org.apache.hadoop.hbase.client.RegionLocator; 071import org.apache.hadoop.hbase.client.Result; 072import org.apache.hadoop.hbase.client.ResultScanner; 073import org.apache.hadoop.hbase.client.Scan; 074import org.apache.hadoop.hbase.client.SnapshotDescription; 075import org.apache.hadoop.hbase.client.Table; 076import org.apache.hadoop.hbase.client.security.SecurityCapability; 077import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 078import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; 079import org.apache.hadoop.hbase.coprocessor.ObserverContextImpl; 080import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 081import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 082import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment; 083import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.CountRequest; 084import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.CountResponse; 085import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.HelloRequest; 086import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.HelloResponse; 087import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.IncrementCountRequest; 088import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.IncrementCountResponse; 089import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.NoopRequest; 090import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.NoopResponse; 091import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingRequest; 092import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingResponse; 093import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingService; 094import org.apache.hadoop.hbase.exceptions.HBaseException; 095import org.apache.hadoop.hbase.io.hfile.CacheConfig; 096import org.apache.hadoop.hbase.io.hfile.HFile; 097import org.apache.hadoop.hbase.io.hfile.HFileContext; 098import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder; 099import org.apache.hadoop.hbase.master.HMaster; 100import org.apache.hadoop.hbase.master.MasterCoprocessorHost; 101import org.apache.hadoop.hbase.master.locking.LockProcedure; 102import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 103import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface; 104import org.apache.hadoop.hbase.procedure2.LockType; 105import org.apache.hadoop.hbase.procedure2.Procedure; 106import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 107import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 108import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 109import org.apache.hadoop.hbase.protobuf.ProtobufUtil; 110import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos; 111import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService; 112import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest; 113import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker; 114import org.apache.hadoop.hbase.regionserver.HRegion; 115import org.apache.hadoop.hbase.regionserver.HRegionServer; 116import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; 117import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost; 118import org.apache.hadoop.hbase.regionserver.ScanType; 119import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; 120import org.apache.hadoop.hbase.security.Superusers; 121import org.apache.hadoop.hbase.security.User; 122import org.apache.hadoop.hbase.security.access.Permission.Action; 123import org.apache.hadoop.hbase.testclassification.LargeTests; 124import org.apache.hadoop.hbase.testclassification.SecurityTests; 125import org.apache.hadoop.hbase.tool.LoadIncrementalHFiles; 126import org.apache.hadoop.hbase.util.Bytes; 127import org.apache.hadoop.hbase.util.JVMClusterUtil; 128import org.apache.hadoop.hbase.util.Threads; 129import org.junit.AfterClass; 130import org.junit.BeforeClass; 131import org.junit.ClassRule; 132import org.junit.Rule; 133import org.junit.Test; 134import org.junit.experimental.categories.Category; 135import org.junit.rules.TestName; 136import org.slf4j.Logger; 137import org.slf4j.LoggerFactory; 138 139import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProcedureProtos; 140import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.ProcedureState; 141 142/** 143 * Performs authorization checks for common operations, according to different 144 * levels of authorized users. 145 */ 146@Category({SecurityTests.class, LargeTests.class}) 147public class TestAccessController extends SecureTestUtil { 148 149 @ClassRule 150 public static final HBaseClassTestRule CLASS_RULE = 151 HBaseClassTestRule.forClass(TestAccessController.class); 152 153 private static final FsPermission FS_PERMISSION_ALL = FsPermission.valueOf("-rwxrwxrwx"); 154 private static final Logger LOG = LoggerFactory.getLogger(TestAccessController.class); 155 private static TableName TEST_TABLE = TableName.valueOf("testtable1"); 156 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 157 private static Configuration conf; 158 159 /** The systemUserConnection created here is tied to the system user. In case, you are planning 160 * to create AccessTestAction, DON'T use this systemUserConnection as the 'doAs' user 161 * gets eclipsed by the system user. */ 162 private static Connection systemUserConnection; 163 164 165 // user with all permissions 166 private static User SUPERUSER; 167 // user granted with all global permission 168 private static User USER_ADMIN; 169 // user with rw permissions on column family. 170 private static User USER_RW; 171 // user with read-only permissions 172 private static User USER_RO; 173 // user is table owner. will have all permissions on table 174 private static User USER_OWNER; 175 // user with create table permissions alone 176 private static User USER_CREATE; 177 // user with no permissions 178 private static User USER_NONE; 179 // user with admin rights on the column family 180 private static User USER_ADMIN_CF; 181 182 private static final String GROUP_ADMIN = "group_admin"; 183 private static final String GROUP_CREATE = "group_create"; 184 private static final String GROUP_READ = "group_read"; 185 private static final String GROUP_WRITE = "group_write"; 186 187 private static User USER_GROUP_ADMIN; 188 private static User USER_GROUP_CREATE; 189 private static User USER_GROUP_READ; 190 private static User USER_GROUP_WRITE; 191 192 // TODO: convert this test to cover the full matrix in 193 // https://hbase.apache.org/book/appendix_acl_matrix.html 194 // creating all Scope x Permission combinations 195 196 private static TableName TEST_TABLE2 = TableName.valueOf("testtable2"); 197 private static byte[] TEST_FAMILY = Bytes.toBytes("f1"); 198 private static byte[] TEST_QUALIFIER = Bytes.toBytes("q1"); 199 private static byte[] TEST_ROW = Bytes.toBytes("r1"); 200 201 private static MasterCoprocessorEnvironment CP_ENV; 202 private static AccessController ACCESS_CONTROLLER; 203 private static RegionServerCoprocessorEnvironment RSCP_ENV; 204 private static RegionCoprocessorEnvironment RCP_ENV; 205 206 @Rule 207 public TestName name = new TestName(); 208 209 @BeforeClass 210 public static void setupBeforeClass() throws Exception { 211 // setup configuration 212 conf = TEST_UTIL.getConfiguration(); 213 // Up the handlers; this test needs more than usual. 214 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); 215 // Enable security 216 enableSecurity(conf); 217 // In this particular test case, we can't use SecureBulkLoadEndpoint because its doAs will fail 218 // to move a file for a random user 219 conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName()); 220 // Verify enableSecurity sets up what we require 221 verifyConfiguration(conf); 222 223 // Enable EXEC permission checking 224 conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true); 225 226 TEST_UTIL.startMiniCluster(); 227 MasterCoprocessorHost masterCpHost = 228 TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost(); 229 masterCpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf); 230 ACCESS_CONTROLLER = masterCpHost.findCoprocessor(AccessController.class); 231 CP_ENV = masterCpHost.createEnvironment( 232 ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); 233 RegionServerCoprocessorHost rsCpHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0) 234 .getRegionServerCoprocessorHost(); 235 RSCP_ENV = rsCpHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); 236 237 // Wait for the ACL table to become available 238 TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME); 239 240 // create a set of test users 241 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 242 USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]); 243 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 244 USER_RO = User.createUserForTesting(conf, "rouser", new String[0]); 245 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]); 246 USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]); 247 USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]); 248 USER_ADMIN_CF = User.createUserForTesting(conf, "col_family_admin", new String[0]); 249 250 USER_GROUP_ADMIN = 251 User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN }); 252 USER_GROUP_CREATE = 253 User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE }); 254 USER_GROUP_READ = 255 User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ }); 256 USER_GROUP_WRITE = 257 User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE }); 258 259 systemUserConnection = TEST_UTIL.getConnection(); 260 setUpTableAndUserPermissions(); 261 } 262 263 @AfterClass 264 public static void tearDownAfterClass() throws Exception { 265 cleanUp(); 266 TEST_UTIL.shutdownMiniCluster(); 267 int total = TableAuthManager.getTotalRefCount(); 268 assertTrue("Unexpected reference count: " + total, total == 0); 269 } 270 271 private static void setUpTableAndUserPermissions() throws Exception { 272 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE); 273 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY); 274 hcd.setMaxVersions(100); 275 htd.addFamily(hcd); 276 htd.setOwner(USER_OWNER); 277 createTable(TEST_UTIL, htd, new byte[][] { Bytes.toBytes("s") }); 278 279 HRegion region = TEST_UTIL.getHBaseCluster().getRegions(TEST_TABLE).get(0); 280 RegionCoprocessorHost rcpHost = region.getCoprocessorHost(); 281 RCP_ENV = rcpHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); 282 283 // Set up initial grants 284 285 grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(), 286 Permission.Action.ADMIN, 287 Permission.Action.CREATE, 288 Permission.Action.READ, 289 Permission.Action.WRITE); 290 291 grantOnTable(TEST_UTIL, USER_RW.getShortName(), 292 TEST_TABLE, TEST_FAMILY, null, 293 Permission.Action.READ, 294 Permission.Action.WRITE); 295 296 // USER_CREATE is USER_RW plus CREATE permissions 297 grantOnTable(TEST_UTIL, USER_CREATE.getShortName(), 298 TEST_TABLE, null, null, 299 Permission.Action.CREATE, 300 Permission.Action.READ, 301 Permission.Action.WRITE); 302 303 grantOnTable(TEST_UTIL, USER_RO.getShortName(), 304 TEST_TABLE, TEST_FAMILY, null, 305 Permission.Action.READ); 306 307 grantOnTable(TEST_UTIL, USER_ADMIN_CF.getShortName(), 308 TEST_TABLE, TEST_FAMILY, 309 null, Permission.Action.ADMIN, Permission.Action.CREATE); 310 311 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN); 312 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE); 313 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ); 314 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE); 315 316 assertEquals(5, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 317 int size = 0; 318 try { 319 size = AccessControlClient.getUserPermissions(systemUserConnection, TEST_TABLE.toString()) 320 .size(); 321 } catch (Throwable e) { 322 LOG.error("error during call of AccessControlClient.getUserPermissions. ", e); 323 fail("error during call of AccessControlClient.getUserPermissions."); 324 } 325 assertEquals(5, size); 326 } 327 328 private static void cleanUp() throws Exception { 329 // Clean the _acl_ table 330 try { 331 deleteTable(TEST_UTIL, TEST_TABLE); 332 } catch (TableNotFoundException ex) { 333 // Test deleted the table, no problem 334 LOG.info("Test deleted table " + TEST_TABLE); 335 } 336 // Verify all table/namespace permissions are erased 337 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 338 assertEquals( 339 0, 340 AccessControlLists.getNamespacePermissions(conf, 341 TEST_TABLE.getNamespaceAsString()).size()); 342 } 343 344 @Test 345 public void testUnauthorizedShutdown() throws Exception { 346 AccessTestAction action = new AccessTestAction() { 347 @Override public Object run() throws Exception { 348 HMaster master = TEST_UTIL.getHBaseCluster().getMaster(); 349 master.shutdown(); 350 return null; 351 } 352 }; 353 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 354 USER_GROUP_WRITE, USER_GROUP_CREATE); 355 } 356 357 @Test 358 public void testUnauthorizedStopMaster() throws Exception { 359 AccessTestAction action = new AccessTestAction() { 360 @Override public Object run() throws Exception { 361 HMaster master = TEST_UTIL.getHBaseCluster().getMaster(); 362 master.stopMaster(); 363 return null; 364 } 365 }; 366 367 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 368 USER_GROUP_WRITE, USER_GROUP_CREATE); 369 } 370 371 @Test 372 public void testSecurityCapabilities() throws Exception { 373 List<SecurityCapability> capabilities = TEST_UTIL.getConnection().getAdmin() 374 .getSecurityCapabilities(); 375 assertTrue("AUTHORIZATION capability is missing", 376 capabilities.contains(SecurityCapability.AUTHORIZATION)); 377 assertTrue("CELL_AUTHORIZATION capability is missing", 378 capabilities.contains(SecurityCapability.CELL_AUTHORIZATION)); 379 } 380 381 @Test 382 public void testTableCreate() throws Exception { 383 AccessTestAction createTable = new AccessTestAction() { 384 @Override 385 public Object run() throws Exception { 386 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 387 htd.addFamily(new HColumnDescriptor(TEST_FAMILY)); 388 ACCESS_CONTROLLER.preCreateTable(ObserverContextImpl.createAndPrepare(CP_ENV), htd, null); 389 return null; 390 } 391 }; 392 393 // verify that superuser can create tables 394 verifyAllowed(createTable, SUPERUSER, USER_ADMIN, USER_GROUP_CREATE); 395 396 // all others should be denied 397 verifyDenied(createTable, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_ADMIN, 398 USER_GROUP_READ, USER_GROUP_WRITE); 399 } 400 401 @Test 402 public void testTableModify() throws Exception { 403 AccessTestAction modifyTable = new AccessTestAction() { 404 @Override 405 public Object run() throws Exception { 406 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE); 407 htd.addFamily(new HColumnDescriptor(TEST_FAMILY)); 408 htd.addFamily(new HColumnDescriptor("fam_" + User.getCurrent().getShortName())); 409 ACCESS_CONTROLLER.preModifyTable(ObserverContextImpl.createAndPrepare(CP_ENV), 410 TEST_TABLE, htd); 411 return null; 412 } 413 }; 414 415 verifyAllowed(modifyTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE, 416 USER_GROUP_ADMIN); 417 verifyDenied(modifyTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 418 } 419 420 @Test 421 public void testTableDelete() throws Exception { 422 AccessTestAction deleteTable = new AccessTestAction() { 423 @Override 424 public Object run() throws Exception { 425 ACCESS_CONTROLLER 426 .preDeleteTable(ObserverContextImpl.createAndPrepare(CP_ENV), TEST_TABLE); 427 return null; 428 } 429 }; 430 431 verifyAllowed(deleteTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE, 432 USER_GROUP_ADMIN); 433 verifyDenied(deleteTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 434 } 435 436 @Test 437 public void testTableTruncate() throws Exception { 438 AccessTestAction truncateTable = new AccessTestAction() { 439 @Override 440 public Object run() throws Exception { 441 ACCESS_CONTROLLER 442 .preTruncateTable(ObserverContextImpl.createAndPrepare(CP_ENV), 443 TEST_TABLE); 444 return null; 445 } 446 }; 447 448 verifyAllowed(truncateTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE, 449 USER_GROUP_ADMIN); 450 verifyDenied(truncateTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 451 } 452 453 @Test 454 public void testTableDisable() throws Exception { 455 AccessTestAction disableTable = new AccessTestAction() { 456 @Override 457 public Object run() throws Exception { 458 ACCESS_CONTROLLER.preDisableTable(ObserverContextImpl.createAndPrepare(CP_ENV), 459 TEST_TABLE); 460 return null; 461 } 462 }; 463 464 AccessTestAction disableAclTable = new AccessTestAction() { 465 @Override 466 public Object run() throws Exception { 467 ACCESS_CONTROLLER.preDisableTable(ObserverContextImpl.createAndPrepare(CP_ENV), 468 AccessControlLists.ACL_TABLE_NAME); 469 return null; 470 } 471 }; 472 473 verifyAllowed(disableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE, 474 USER_GROUP_ADMIN); 475 verifyDenied(disableTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 476 477 // No user should be allowed to disable _acl_ table 478 verifyDenied(disableAclTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 479 USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_WRITE); 480 } 481 482 @Test 483 public void testTableEnable() throws Exception { 484 AccessTestAction enableTable = new AccessTestAction() { 485 @Override 486 public Object run() throws Exception { 487 ACCESS_CONTROLLER 488 .preEnableTable(ObserverContextImpl.createAndPrepare(CP_ENV), TEST_TABLE); 489 return null; 490 } 491 }; 492 493 verifyAllowed(enableTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_GROUP_CREATE, 494 USER_GROUP_ADMIN); 495 verifyDenied(enableTable, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 496 } 497 498 public static class TestTableDDLProcedure extends Procedure<MasterProcedureEnv> 499 implements TableProcedureInterface { 500 private TableName tableName; 501 502 public TestTableDDLProcedure() { 503 } 504 505 public TestTableDDLProcedure(final MasterProcedureEnv env, final TableName tableName) 506 throws IOException { 507 this.tableName = tableName; 508 this.setTimeout(180000); // Timeout in 3 minutes 509 this.setOwner(env.getRequestUser()); 510 } 511 512 @Override 513 public TableName getTableName() { 514 return tableName; 515 } 516 517 @Override 518 public TableOperationType getTableOperationType() { 519 return TableOperationType.EDIT; 520 } 521 522 @Override 523 protected boolean abort(MasterProcedureEnv env) { 524 return true; 525 } 526 527 @Override 528 protected void serializeStateData(ProcedureStateSerializer serializer) 529 throws IOException { 530 TestProcedureProtos.TestTableDDLStateData.Builder testTableDDLMsg = 531 TestProcedureProtos.TestTableDDLStateData.newBuilder() 532 .setTableName(tableName.getNameAsString()); 533 serializer.serialize(testTableDDLMsg.build()); 534 } 535 536 @Override 537 protected void deserializeStateData(ProcedureStateSerializer serializer) 538 throws IOException { 539 TestProcedureProtos.TestTableDDLStateData testTableDDLMsg = 540 serializer.deserialize(TestProcedureProtos.TestTableDDLStateData.class); 541 tableName = TableName.valueOf(testTableDDLMsg.getTableName()); 542 } 543 544 @Override 545 protected Procedure[] execute(MasterProcedureEnv env) throws ProcedureYieldException, 546 InterruptedException { 547 // Not letting the procedure to complete until timed out 548 setState(ProcedureState.WAITING_TIMEOUT); 549 return null; 550 } 551 552 @Override 553 protected void rollback(MasterProcedureEnv env) throws IOException, InterruptedException { 554 } 555 } 556 557 @Test 558 public void testAbortProcedure() throws Exception { 559 long procId = 1; 560 AccessTestAction abortProcedureAction = new AccessTestAction() { 561 @Override 562 public Object run() throws Exception { 563 ACCESS_CONTROLLER.preAbortProcedure(ObserverContextImpl.createAndPrepare(CP_ENV), procId); 564 return null; 565 } 566 }; 567 568 verifyAllowed(abortProcedureAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 569 } 570 571 @Test 572 public void testGetProcedures() throws Exception { 573 final TableName tableName = TableName.valueOf(name.getMethodName()); 574 final ProcedureExecutor<MasterProcedureEnv> procExec = 575 TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 576 Procedure proc = new TestTableDDLProcedure(procExec.getEnvironment(), tableName); 577 proc.setOwner(USER_OWNER); 578 procExec.submitProcedure(proc); 579 final List<Procedure<MasterProcedureEnv>> procList = procExec.getProcedures(); 580 581 AccessTestAction getProceduresAction = new AccessTestAction() { 582 @Override 583 public Object run() throws Exception { 584 ACCESS_CONTROLLER 585 .postGetProcedures(ObserverContextImpl.createAndPrepare(CP_ENV)); 586 return null; 587 } 588 }; 589 590 verifyAllowed(getProceduresAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 591 verifyAllowed(getProceduresAction, USER_OWNER); 592 verifyIfNull( 593 getProceduresAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 594 } 595 596 @Test 597 public void testGetLocks() throws Exception { 598 AccessTestAction action = new AccessTestAction() { 599 @Override 600 public Object run() throws Exception { 601 ACCESS_CONTROLLER.preGetLocks(ObserverContextImpl.createAndPrepare(CP_ENV)); 602 return null; 603 } 604 }; 605 606 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 607 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, 608 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 609 } 610 611 @Test 612 public void testMove() throws Exception { 613 List<HRegionLocation> regions; 614 try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) { 615 regions = locator.getAllRegionLocations(); 616 } 617 HRegionLocation location = regions.get(0); 618 final HRegionInfo hri = location.getRegionInfo(); 619 final ServerName server = location.getServerName(); 620 AccessTestAction action = new AccessTestAction() { 621 @Override 622 public Object run() throws Exception { 623 ACCESS_CONTROLLER.preMove(ObserverContextImpl.createAndPrepare(CP_ENV), 624 hri, server, server); 625 return null; 626 } 627 }; 628 629 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 630 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 631 USER_GROUP_WRITE, USER_GROUP_CREATE); 632 } 633 634 @Test 635 public void testAssign() throws Exception { 636 List<HRegionLocation> regions; 637 try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) { 638 regions = locator.getAllRegionLocations(); 639 } 640 HRegionLocation location = regions.get(0); 641 final HRegionInfo hri = location.getRegionInfo(); 642 AccessTestAction action = new AccessTestAction() { 643 @Override 644 public Object run() throws Exception { 645 ACCESS_CONTROLLER.preAssign(ObserverContextImpl.createAndPrepare(CP_ENV), hri); 646 return null; 647 } 648 }; 649 650 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 651 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 652 USER_GROUP_WRITE, USER_GROUP_CREATE); 653 } 654 655 @Test 656 public void testUnassign() throws Exception { 657 List<HRegionLocation> regions; 658 try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) { 659 regions = locator.getAllRegionLocations(); 660 } 661 HRegionLocation location = regions.get(0); 662 final HRegionInfo hri = location.getRegionInfo(); 663 AccessTestAction action = new AccessTestAction() { 664 @Override 665 public Object run() throws Exception { 666 ACCESS_CONTROLLER.preUnassign(ObserverContextImpl.createAndPrepare(CP_ENV), hri, false); 667 return null; 668 } 669 }; 670 671 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 672 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 673 USER_GROUP_WRITE, USER_GROUP_CREATE); 674 } 675 676 @Test 677 public void testRegionOffline() throws Exception { 678 List<HRegionLocation> regions; 679 try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE)) { 680 regions = locator.getAllRegionLocations(); 681 } 682 HRegionLocation location = regions.get(0); 683 final HRegionInfo hri = location.getRegionInfo(); 684 AccessTestAction action = new AccessTestAction() { 685 @Override 686 public Object run() throws Exception { 687 ACCESS_CONTROLLER.preRegionOffline(ObserverContextImpl.createAndPrepare(CP_ENV), hri); 688 return null; 689 } 690 }; 691 692 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 693 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 694 USER_GROUP_WRITE, USER_GROUP_CREATE); 695 } 696 697 @Test 698 public void testSetSplitOrMergeEnabled() throws Exception { 699 AccessTestAction action = new AccessTestAction() { 700 @Override 701 public Object run() throws Exception { 702 ACCESS_CONTROLLER.preSetSplitOrMergeEnabled(ObserverContextImpl.createAndPrepare(CP_ENV), 703 true, MasterSwitchType.MERGE); 704 return null; 705 } 706 }; 707 708 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 709 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 710 USER_GROUP_WRITE, USER_GROUP_CREATE); 711 } 712 713 @Test 714 public void testBalance() throws Exception { 715 AccessTestAction action = new AccessTestAction() { 716 @Override 717 public Object run() throws Exception { 718 ACCESS_CONTROLLER.preBalance(ObserverContextImpl.createAndPrepare(CP_ENV)); 719 return null; 720 } 721 }; 722 723 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 724 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 725 USER_GROUP_WRITE, USER_GROUP_CREATE); 726 } 727 728 @Test 729 public void testBalanceSwitch() throws Exception { 730 AccessTestAction action = new AccessTestAction() { 731 @Override 732 public Object run() throws Exception { 733 ACCESS_CONTROLLER.preBalanceSwitch(ObserverContextImpl.createAndPrepare(CP_ENV), true); 734 return null; 735 } 736 }; 737 738 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 739 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 740 USER_GROUP_WRITE, USER_GROUP_CREATE); 741 } 742 743 @Test 744 public void testShutdown() throws Exception { 745 AccessTestAction action = new AccessTestAction() { 746 @Override 747 public Object run() throws Exception { 748 ACCESS_CONTROLLER.preShutdown(ObserverContextImpl.createAndPrepare(CP_ENV)); 749 return null; 750 } 751 }; 752 753 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 754 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 755 USER_GROUP_WRITE, USER_GROUP_CREATE); 756 } 757 758 @Test 759 public void testStopMaster() throws Exception { 760 AccessTestAction action = new AccessTestAction() { 761 @Override 762 public Object run() throws Exception { 763 ACCESS_CONTROLLER.preStopMaster(ObserverContextImpl.createAndPrepare(CP_ENV)); 764 return null; 765 } 766 }; 767 768 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 769 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 770 USER_GROUP_WRITE, USER_GROUP_CREATE); 771 } 772 773 private void verifyWrite(AccessTestAction action) throws Exception { 774 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, 775 USER_GROUP_WRITE); 776 verifyDenied(action, USER_NONE, USER_RO, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_CREATE); 777 } 778 779 @Test 780 public void testSplitWithSplitRow() throws Exception { 781 final TableName tableName = TableName.valueOf(name.getMethodName()); 782 createTestTable(tableName); 783 AccessTestAction action = new AccessTestAction() { 784 @Override 785 public Object run() throws Exception { 786 ACCESS_CONTROLLER.preSplitRegion( 787 ObserverContextImpl.createAndPrepare(CP_ENV), 788 tableName, 789 TEST_ROW); 790 return null; 791 } 792 }; 793 794 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 795 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 796 USER_GROUP_WRITE, USER_GROUP_CREATE); 797 } 798 799 @Test 800 public void testFlush() throws Exception { 801 AccessTestAction action = new AccessTestAction() { 802 @Override 803 public Object run() throws Exception { 804 ACCESS_CONTROLLER.preFlush(ObserverContextImpl.createAndPrepare(RCP_ENV), 805 FlushLifeCycleTracker.DUMMY); 806 return null; 807 } 808 }; 809 810 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_GROUP_CREATE, 811 USER_GROUP_ADMIN); 812 verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 813 } 814 815 @Test 816 public void testCompact() throws Exception { 817 AccessTestAction action = new AccessTestAction() { 818 @Override 819 public Object run() throws Exception { 820 ACCESS_CONTROLLER.preCompact(ObserverContextImpl.createAndPrepare(RCP_ENV), null, null, 821 ScanType.COMPACT_RETAIN_DELETES, null, null); 822 return null; 823 } 824 }; 825 826 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_GROUP_CREATE, 827 USER_GROUP_ADMIN); 828 verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); 829 } 830 831 private void verifyRead(AccessTestAction action) throws Exception { 832 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO, 833 USER_GROUP_READ); 834 verifyDenied(action, USER_NONE, USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_WRITE); 835 } 836 837 private void verifyReadWrite(AccessTestAction action) throws Exception { 838 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW); 839 verifyDenied(action, USER_NONE, USER_RO, USER_GROUP_ADMIN, USER_GROUP_CREATE, USER_GROUP_READ, 840 USER_GROUP_WRITE); 841 } 842 843 @Test 844 public void testRead() throws Exception { 845 // get action 846 AccessTestAction getAction = new AccessTestAction() { 847 @Override 848 public Object run() throws Exception { 849 Get g = new Get(TEST_ROW); 850 g.addFamily(TEST_FAMILY); 851 try(Connection conn = ConnectionFactory.createConnection(conf); 852 Table t = conn.getTable(TEST_TABLE)) { 853 t.get(g); 854 } 855 return null; 856 } 857 }; 858 verifyRead(getAction); 859 860 // action for scanning 861 AccessTestAction scanAction = new AccessTestAction() { 862 @Override 863 public Object run() throws Exception { 864 Scan s = new Scan(); 865 s.addFamily(TEST_FAMILY); 866 try(Connection conn = ConnectionFactory.createConnection(conf); 867 Table table = conn.getTable(TEST_TABLE)) { 868 ResultScanner scanner = table.getScanner(s); 869 try { 870 for (Result r = scanner.next(); r != null; r = scanner.next()) { 871 // do nothing 872 } 873 } finally { 874 scanner.close(); 875 } 876 } 877 return null; 878 } 879 }; 880 verifyRead(scanAction); 881 } 882 883 @Test 884 // test put, delete, increment 885 public void testWrite() throws Exception { 886 // put action 887 AccessTestAction putAction = new AccessTestAction() { 888 @Override 889 public Object run() throws Exception { 890 Put p = new Put(TEST_ROW); 891 p.addColumn(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1)); 892 try(Connection conn = ConnectionFactory.createConnection(conf); 893 Table t = conn.getTable(TEST_TABLE)) { 894 t.put(p); 895 } 896 return null; 897 } 898 }; 899 verifyWrite(putAction); 900 901 // delete action 902 AccessTestAction deleteAction = new AccessTestAction() { 903 @Override 904 public Object run() throws Exception { 905 Delete d = new Delete(TEST_ROW); 906 d.addFamily(TEST_FAMILY); 907 try(Connection conn = ConnectionFactory.createConnection(conf); 908 Table t = conn.getTable(TEST_TABLE)) { 909 t.delete(d); 910 } 911 return null; 912 } 913 }; 914 verifyWrite(deleteAction); 915 916 // increment action 917 AccessTestAction incrementAction = new AccessTestAction() { 918 @Override 919 public Object run() throws Exception { 920 Increment inc = new Increment(TEST_ROW); 921 inc.addColumn(TEST_FAMILY, TEST_QUALIFIER, 1); 922 try(Connection conn = ConnectionFactory.createConnection(conf); 923 Table t = conn.getTable(TEST_TABLE);) { 924 t.increment(inc); 925 } 926 return null; 927 } 928 }; 929 verifyWrite(incrementAction); 930 } 931 932 @Test 933 public void testReadWrite() throws Exception { 934 // action for checkAndDelete 935 AccessTestAction checkAndDeleteAction = new AccessTestAction() { 936 @Override 937 public Object run() throws Exception { 938 Delete d = new Delete(TEST_ROW); 939 d.addFamily(TEST_FAMILY); 940 try(Connection conn = ConnectionFactory.createConnection(conf); 941 Table t = conn.getTable(TEST_TABLE);) { 942 t.checkAndMutate(TEST_ROW, TEST_FAMILY).qualifier(TEST_QUALIFIER) 943 .ifEquals(Bytes.toBytes("test_value")).thenDelete(d); 944 } 945 return null; 946 } 947 }; 948 verifyReadWrite(checkAndDeleteAction); 949 950 // action for checkAndPut() 951 AccessTestAction checkAndPut = new AccessTestAction() { 952 @Override 953 public Object run() throws Exception { 954 Put p = new Put(TEST_ROW); 955 p.addColumn(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1)); 956 try(Connection conn = ConnectionFactory.createConnection(conf); 957 Table t = conn.getTable(TEST_TABLE)) { 958 t.checkAndMutate(TEST_ROW, TEST_FAMILY).qualifier(TEST_QUALIFIER) 959 .ifEquals(Bytes.toBytes("test_value")).thenPut(p); 960 } 961 return null; 962 } 963 }; 964 verifyReadWrite(checkAndPut); 965 } 966 967 @Test 968 public void testBulkLoad() throws Exception { 969 try { 970 FileSystem fs = TEST_UTIL.getTestFileSystem(); 971 final Path dir = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoad"); 972 fs.mkdirs(dir); 973 // need to make it globally writable 974 // so users creating HFiles have write permissions 975 fs.setPermission(dir, FS_PERMISSION_ALL); 976 977 AccessTestAction bulkLoadAction = new AccessTestAction() { 978 @Override 979 public Object run() throws Exception { 980 int numRows = 3; 981 982 // Making the assumption that the test table won't split between the range 983 byte[][][] hfileRanges = { { { (byte) 0 }, { (byte) 9 } } }; 984 985 Path bulkLoadBasePath = new Path(dir, new Path(User.getCurrent().getName())); 986 new BulkLoadHelper(bulkLoadBasePath).initHFileData(TEST_FAMILY, TEST_QUALIFIER, 987 hfileRanges, numRows, FS_PERMISSION_ALL).bulkLoadHFile(TEST_TABLE); 988 return null; 989 } 990 }; 991 992 // User performing bulk loads must have privilege to read table metadata 993 // (ADMIN or CREATE) 994 verifyAllowed(bulkLoadAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, 995 USER_GROUP_CREATE); 996 verifyDenied(bulkLoadAction, USER_RW, USER_NONE, USER_RO, USER_GROUP_READ, USER_GROUP_WRITE, 997 USER_GROUP_ADMIN); 998 } finally { 999 // Reinit after the bulk upload 1000 TEST_UTIL.getAdmin().disableTable(TEST_TABLE); 1001 TEST_UTIL.getAdmin().enableTable(TEST_TABLE); 1002 } 1003 } 1004 1005 private class BulkLoadAccessTestAction implements AccessTestAction { 1006 private FsPermission filePermission; 1007 private Path testDataDir; 1008 1009 public BulkLoadAccessTestAction(FsPermission perm, Path testDataDir) { 1010 this.filePermission = perm; 1011 this.testDataDir = testDataDir; 1012 } 1013 1014 @Override 1015 public Object run() throws Exception { 1016 FileSystem fs = TEST_UTIL.getTestFileSystem(); 1017 fs.mkdirs(testDataDir); 1018 fs.setPermission(testDataDir, FS_PERMISSION_ALL); 1019 // Making the assumption that the test table won't split between the range 1020 byte[][][] hfileRanges = { { { (byte) 0 }, { (byte) 9 } } }; 1021 Path bulkLoadBasePath = new Path(testDataDir, new Path(User.getCurrent().getName())); 1022 new BulkLoadHelper(bulkLoadBasePath) 1023 .initHFileData(TEST_FAMILY, TEST_QUALIFIER, hfileRanges, 3, filePermission) 1024 .bulkLoadHFile(TEST_TABLE); 1025 return null; 1026 } 1027 } 1028 1029 @Test 1030 public void testBulkLoadWithoutWritePermission() throws Exception { 1031 // Use the USER_CREATE to initialize the source directory. 1032 Path testDataDir0 = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoadWithoutWritePermission0"); 1033 Path testDataDir1 = TEST_UTIL.getDataTestDirOnTestFS("testBulkLoadWithoutWritePermission1"); 1034 AccessTestAction bulkLoadAction1 = 1035 new BulkLoadAccessTestAction(FsPermission.valueOf("-r-xr-xr-x"), testDataDir0); 1036 AccessTestAction bulkLoadAction2 = 1037 new BulkLoadAccessTestAction(FS_PERMISSION_ALL, testDataDir1); 1038 // Test the incorrect case. 1039 BulkLoadHelper.setPermission(TEST_UTIL.getTestFileSystem(), 1040 TEST_UTIL.getTestFileSystem().getWorkingDirectory(), FS_PERMISSION_ALL); 1041 try { 1042 USER_CREATE.runAs(bulkLoadAction1); 1043 fail("Should fail because the hbase user has no write permission on hfiles."); 1044 } catch (IOException e) { 1045 } 1046 // Ensure the correct case. 1047 USER_CREATE.runAs(bulkLoadAction2); 1048 } 1049 1050 public static class BulkLoadHelper { 1051 private final FileSystem fs; 1052 private final Path loadPath; 1053 private final Configuration conf; 1054 1055 public BulkLoadHelper(Path loadPath) throws IOException { 1056 fs = TEST_UTIL.getTestFileSystem(); 1057 conf = TEST_UTIL.getConfiguration(); 1058 loadPath = loadPath.makeQualified(fs); 1059 this.loadPath = loadPath; 1060 } 1061 1062 private void createHFile(Path path, 1063 byte[] family, byte[] qualifier, 1064 byte[] startKey, byte[] endKey, int numRows) throws IOException { 1065 HFile.Writer writer = null; 1066 long now = System.currentTimeMillis(); 1067 try { 1068 HFileContext context = new HFileContextBuilder().build(); 1069 writer = HFile.getWriterFactory(conf, new CacheConfig(conf)).withPath(fs, path) 1070 .withFileContext(context).create(); 1071 // subtract 2 since numRows doesn't include boundary keys 1072 for (byte[] key : Bytes.iterateOnSplits(startKey, endKey, true, numRows - 2)) { 1073 KeyValue kv = new KeyValue(key, family, qualifier, now, key); 1074 writer.append(kv); 1075 } 1076 } finally { 1077 if (writer != null) { 1078 writer.close(); 1079 } 1080 } 1081 } 1082 1083 private BulkLoadHelper initHFileData(byte[] family, byte[] qualifier, byte[][][] hfileRanges, 1084 int numRowsPerRange, FsPermission filePermission) throws Exception { 1085 Path familyDir = new Path(loadPath, Bytes.toString(family)); 1086 fs.mkdirs(familyDir); 1087 int hfileIdx = 0; 1088 List<Path> hfiles = new ArrayList<>(); 1089 for (byte[][] range : hfileRanges) { 1090 byte[] from = range[0]; 1091 byte[] to = range[1]; 1092 Path hfile = new Path(familyDir, "hfile_" + (hfileIdx++)); 1093 hfiles.add(hfile); 1094 createHFile(hfile, family, qualifier, from, to, numRowsPerRange); 1095 } 1096 // set global read so RegionServer can move it 1097 setPermission(fs, loadPath, FS_PERMISSION_ALL); 1098 // Ensure the file permission as requested. 1099 for (Path hfile : hfiles) { 1100 setPermission(fs, hfile, filePermission); 1101 } 1102 return this; 1103 } 1104 1105 private void bulkLoadHFile(TableName tableName) throws Exception { 1106 try (Connection conn = ConnectionFactory.createConnection(conf); 1107 Admin admin = conn.getAdmin(); 1108 RegionLocator locator = conn.getRegionLocator(tableName); 1109 Table table = conn.getTable(tableName)) { 1110 TEST_UTIL.waitUntilAllRegionsAssigned(tableName); 1111 LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf); 1112 loader.doBulkLoad(loadPath, admin, table, locator); 1113 } 1114 } 1115 1116 private static void setPermission(FileSystem fs, Path dir, FsPermission perm) 1117 throws IOException { 1118 if (!fs.getFileStatus(dir).isDirectory()) { 1119 fs.setPermission(dir, perm); 1120 } else { 1121 for (FileStatus el : fs.listStatus(dir)) { 1122 fs.setPermission(el.getPath(), perm); 1123 setPermission(fs, el.getPath(), perm); 1124 } 1125 } 1126 } 1127 } 1128 1129 @Test 1130 public void testAppend() throws Exception { 1131 1132 AccessTestAction appendAction = new AccessTestAction() { 1133 @Override 1134 public Object run() throws Exception { 1135 byte[] row = TEST_ROW; 1136 byte[] qualifier = TEST_QUALIFIER; 1137 Put put = new Put(row); 1138 put.addColumn(TEST_FAMILY, qualifier, Bytes.toBytes(1)); 1139 Append append = new Append(row); 1140 append.addColumn(TEST_FAMILY, qualifier, Bytes.toBytes(2)); 1141 try(Connection conn = ConnectionFactory.createConnection(conf); 1142 Table t = conn.getTable(TEST_TABLE)) { 1143 t.put(put); 1144 t.append(append); 1145 } 1146 return null; 1147 } 1148 }; 1149 1150 verifyAllowed(appendAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, 1151 USER_GROUP_WRITE); 1152 verifyDenied(appendAction, USER_RO, USER_NONE, USER_GROUP_CREATE, USER_GROUP_READ, 1153 USER_GROUP_ADMIN); 1154 } 1155 1156 @Test 1157 public void testGrantRevoke() throws Exception { 1158 AccessTestAction grantAction = new AccessTestAction() { 1159 @Override 1160 public Object run() throws Exception { 1161 try(Connection conn = ConnectionFactory.createConnection(conf); 1162 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { 1163 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); 1164 AccessControlService.BlockingInterface protocol = 1165 AccessControlService.newBlockingStub(service); 1166 AccessControlUtil.grant(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, 1167 null, false, Action.READ); 1168 } 1169 return null; 1170 } 1171 }; 1172 1173 AccessTestAction revokeAction = new AccessTestAction() { 1174 @Override 1175 public Object run() throws Exception { 1176 try(Connection conn = ConnectionFactory.createConnection(conf); 1177 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { 1178 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); 1179 AccessControlService.BlockingInterface protocol = 1180 AccessControlService.newBlockingStub(service); 1181 AccessControlUtil.revoke(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null, 1182 Action.READ); 1183 } 1184 return null; 1185 } 1186 }; 1187 1188 AccessTestAction getTablePermissionsAction = new AccessTestAction() { 1189 @Override 1190 public Object run() throws Exception { 1191 try(Connection conn = ConnectionFactory.createConnection(conf); 1192 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)){ 1193 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); 1194 AccessControlService.BlockingInterface protocol = 1195 AccessControlService.newBlockingStub(service); 1196 AccessControlUtil.getUserPermissions(null, protocol, TEST_TABLE); 1197 } 1198 return null; 1199 } 1200 }; 1201 1202 AccessTestAction getGlobalPermissionsAction = new AccessTestAction() { 1203 @Override 1204 public Object run() throws Exception { 1205 try(Connection conn = ConnectionFactory.createConnection(conf); 1206 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME);) { 1207 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); 1208 AccessControlService.BlockingInterface protocol = 1209 AccessControlService.newBlockingStub(service); 1210 AccessControlUtil.getUserPermissions(null, protocol); 1211 } 1212 return null; 1213 } 1214 }; 1215 1216 verifyAllowed(grantAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 1217 verifyDenied(grantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 1218 USER_GROUP_WRITE, USER_GROUP_CREATE); 1219 try { 1220 verifyAllowed(revokeAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 1221 verifyDenied(revokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 1222 USER_GROUP_WRITE, USER_GROUP_CREATE); 1223 1224 verifyAllowed(getTablePermissionsAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 1225 verifyDenied(getTablePermissionsAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, 1226 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 1227 1228 verifyAllowed(getGlobalPermissionsAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 1229 verifyDenied(getGlobalPermissionsAction, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 1230 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 1231 } finally { 1232 // Cleanup, Grant the revoked permission back to the user 1233 grantOnTable(TEST_UTIL, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null, 1234 Permission.Action.READ); 1235 } 1236 } 1237 1238 @Test 1239 public void testPostGrantRevoke() throws Exception { 1240 final TableName tableName = 1241 TableName.valueOf("TempTable"); 1242 final byte[] family1 = Bytes.toBytes("f1"); 1243 final byte[] family2 = Bytes.toBytes("f2"); 1244 final byte[] qualifier = Bytes.toBytes("q"); 1245 1246 // create table 1247 Admin admin = TEST_UTIL.getAdmin(); 1248 if (admin.tableExists(tableName)) { 1249 deleteTable(TEST_UTIL, tableName); 1250 } 1251 HTableDescriptor htd = new HTableDescriptor(tableName); 1252 htd.addFamily(new HColumnDescriptor(family1)); 1253 htd.addFamily(new HColumnDescriptor(family2)); 1254 createTable(TEST_UTIL, htd); 1255 try { 1256 // create temp users 1257 User tblUser = 1258 User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser", new String[0]); 1259 User gblUser = 1260 User.createUserForTesting(TEST_UTIL.getConfiguration(), "gbluser", new String[0]); 1261 1262 // prepare actions: 1263 AccessTestAction putActionAll = new AccessTestAction() { 1264 @Override 1265 public Object run() throws Exception { 1266 Put p = new Put(Bytes.toBytes("a")); 1267 p.addColumn(family1, qualifier, Bytes.toBytes("v1")); 1268 p.addColumn(family2, qualifier, Bytes.toBytes("v2")); 1269 1270 try (Connection conn = ConnectionFactory.createConnection(conf); 1271 Table t = conn.getTable(tableName);) { 1272 t.put(p); 1273 } 1274 return null; 1275 } 1276 }; 1277 1278 AccessTestAction putAction1 = new AccessTestAction() { 1279 @Override 1280 public Object run() throws Exception { 1281 Put p = new Put(Bytes.toBytes("a")); 1282 p.addColumn(family1, qualifier, Bytes.toBytes("v1")); 1283 1284 try (Connection conn = ConnectionFactory.createConnection(conf); 1285 Table t = conn.getTable(tableName)) { 1286 t.put(p); 1287 } 1288 return null; 1289 } 1290 }; 1291 1292 AccessTestAction putAction2 = new AccessTestAction() { 1293 @Override 1294 public Object run() throws Exception { 1295 Put p = new Put(Bytes.toBytes("a")); 1296 p.addColumn(family2, qualifier, Bytes.toBytes("v2")); 1297 try (Connection conn = ConnectionFactory.createConnection(conf); 1298 Table t = conn.getTable(tableName);) { 1299 t.put(p); 1300 } 1301 return null; 1302 } 1303 }; 1304 1305 AccessTestAction getActionAll = new AccessTestAction() { 1306 @Override 1307 public Object run() throws Exception { 1308 Get g = new Get(TEST_ROW); 1309 g.addFamily(family1); 1310 g.addFamily(family2); 1311 try (Connection conn = ConnectionFactory.createConnection(conf); 1312 Table t = conn.getTable(tableName);) { 1313 t.get(g); 1314 } 1315 return null; 1316 } 1317 }; 1318 1319 AccessTestAction getAction1 = new AccessTestAction() { 1320 @Override 1321 public Object run() throws Exception { 1322 Get g = new Get(TEST_ROW); 1323 g.addFamily(family1); 1324 try (Connection conn = ConnectionFactory.createConnection(conf); 1325 Table t = conn.getTable(tableName)) { 1326 t.get(g); 1327 } 1328 return null; 1329 } 1330 }; 1331 1332 AccessTestAction getAction2 = new AccessTestAction() { 1333 @Override 1334 public Object run() throws Exception { 1335 Get g = new Get(TEST_ROW); 1336 g.addFamily(family2); 1337 try (Connection conn = ConnectionFactory.createConnection(conf); 1338 Table t = conn.getTable(tableName)) { 1339 t.get(g); 1340 } 1341 return null; 1342 } 1343 }; 1344 1345 AccessTestAction deleteActionAll = new AccessTestAction() { 1346 @Override 1347 public Object run() throws Exception { 1348 Delete d = new Delete(TEST_ROW); 1349 d.addFamily(family1); 1350 d.addFamily(family2); 1351 try (Connection conn = ConnectionFactory.createConnection(conf); 1352 Table t = conn.getTable(tableName)) { 1353 t.delete(d); 1354 } 1355 return null; 1356 } 1357 }; 1358 1359 AccessTestAction deleteAction1 = new AccessTestAction() { 1360 @Override 1361 public Object run() throws Exception { 1362 Delete d = new Delete(TEST_ROW); 1363 d.addFamily(family1); 1364 try (Connection conn = ConnectionFactory.createConnection(conf); 1365 Table t = conn.getTable(tableName)) { 1366 t.delete(d); 1367 } 1368 return null; 1369 } 1370 }; 1371 1372 AccessTestAction deleteAction2 = new AccessTestAction() { 1373 @Override 1374 public Object run() throws Exception { 1375 Delete d = new Delete(TEST_ROW); 1376 d.addFamily(family2); 1377 try (Connection conn = ConnectionFactory.createConnection(conf); 1378 Table t = conn.getTable(tableName)) { 1379 t.delete(d); 1380 } 1381 return null; 1382 } 1383 }; 1384 1385 // initial check: 1386 verifyDenied(tblUser, getActionAll, getAction1, getAction2); 1387 verifyDenied(tblUser, putActionAll, putAction1, putAction2); 1388 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1389 1390 verifyDenied(gblUser, getActionAll, getAction1, getAction2); 1391 verifyDenied(gblUser, putActionAll, putAction1, putAction2); 1392 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1393 1394 // grant table read permission 1395 grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.READ); 1396 grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null, Permission.Action.READ); 1397 1398 // check 1399 verifyAllowed(tblUser, getActionAll, getAction1, getAction2); 1400 verifyDenied(tblUser, putActionAll, putAction1, putAction2); 1401 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1402 1403 verifyAllowed(gblUser, getActionAll, getAction1, getAction2); 1404 verifyDenied(gblUser, putActionAll, putAction1, putAction2); 1405 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1406 1407 // grant table write permission while revoking read permissions 1408 grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.WRITE); 1409 grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null, 1410 Permission.Action.WRITE); 1411 1412 verifyDenied(tblUser, getActionAll, getAction1, getAction2); 1413 verifyAllowed(tblUser, putActionAll, putAction1, putAction2); 1414 verifyAllowed(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1415 1416 verifyDenied(gblUser, getActionAll, getAction1, getAction2); 1417 verifyAllowed(gblUser, putActionAll, putAction1, putAction2); 1418 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1419 1420 // revoke table permissions 1421 revokeGlobal(TEST_UTIL, gblUser.getShortName()); 1422 revokeFromTable(TEST_UTIL, tblUser.getShortName(), tableName, null, null); 1423 1424 verifyDenied(tblUser, getActionAll, getAction1, getAction2); 1425 verifyDenied(tblUser, putActionAll, putAction1, putAction2); 1426 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1427 1428 verifyDenied(gblUser, getActionAll, getAction1, getAction2); 1429 verifyDenied(gblUser, putActionAll, putAction1, putAction2); 1430 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1431 1432 // grant column family read permission 1433 grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.READ); 1434 grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, family1, null, 1435 Permission.Action.READ); 1436 1437 // Access should be denied for family2 1438 verifyAllowed(tblUser, getActionAll, getAction1); 1439 verifyDenied(tblUser, getAction2); 1440 verifyDenied(tblUser, putActionAll, putAction1, putAction2); 1441 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1442 1443 verifyAllowed(gblUser, getActionAll, getAction1, getAction2); 1444 verifyDenied(gblUser, putActionAll, putAction1, putAction2); 1445 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1446 1447 // grant column family write permission 1448 grantGlobal(TEST_UTIL, gblUser.getShortName(), Permission.Action.WRITE); 1449 grantOnTable(TEST_UTIL, tblUser.getShortName(), tableName, family2, null, 1450 Permission.Action.WRITE); 1451 1452 // READ from family1, WRITE to family2 are allowed 1453 verifyAllowed(tblUser, getActionAll, getAction1); 1454 verifyAllowed(tblUser, putAction2, deleteAction2); 1455 verifyDenied(tblUser, getAction2); 1456 verifyDenied(tblUser, putActionAll, putAction1); 1457 verifyDenied(tblUser, deleteActionAll, deleteAction1); 1458 1459 verifyDenied(gblUser, getActionAll, getAction1, getAction2); 1460 verifyAllowed(gblUser, putActionAll, putAction1, putAction2); 1461 verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1462 1463 // revoke column family permission 1464 revokeGlobal(TEST_UTIL, gblUser.getShortName()); 1465 revokeFromTable(TEST_UTIL, tblUser.getShortName(), tableName, family2, null); 1466 1467 // Revoke on family2 should not have impact on family1 permissions 1468 verifyAllowed(tblUser, getActionAll, getAction1); 1469 verifyDenied(tblUser, getAction2); 1470 verifyDenied(tblUser, putActionAll, putAction1, putAction2); 1471 verifyDenied(tblUser, deleteActionAll, deleteAction1, deleteAction2); 1472 1473 // Should not have access as global permissions are completely revoked 1474 verifyDenied(gblUser, getActionAll, getAction1, getAction2); 1475 verifyDenied(gblUser, putActionAll, putAction1, putAction2); 1476 verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); 1477 } finally { 1478 // delete table 1479 deleteTable(TEST_UTIL, tableName); 1480 } 1481 } 1482 1483 private boolean hasFoundUserPermission(List<UserPermission> userPermissions, 1484 List<UserPermission> perms) { 1485 return perms.containsAll(userPermissions); 1486 } 1487 1488 private boolean hasFoundUserPermission(UserPermission userPermission, List<UserPermission> perms) { 1489 return perms.contains(userPermission); 1490 } 1491 1492 @Test 1493 public void testPostGrantRevokeAtQualifierLevel() throws Exception { 1494 final TableName tableName = TableName.valueOf(name.getMethodName()); 1495 final byte[] family1 = Bytes.toBytes("f1"); 1496 final byte[] family2 = Bytes.toBytes("f2"); 1497 final byte[] qualifier = Bytes.toBytes("q"); 1498 1499 // create table 1500 Admin admin = TEST_UTIL.getAdmin(); 1501 if (admin.tableExists(tableName)) { 1502 deleteTable(TEST_UTIL, tableName); 1503 } 1504 HTableDescriptor htd = new HTableDescriptor(tableName); 1505 htd.addFamily(new HColumnDescriptor(family1)); 1506 htd.addFamily(new HColumnDescriptor(family2)); 1507 createTable(TEST_UTIL, htd); 1508 1509 try { 1510 // create temp users 1511 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]); 1512 1513 AccessTestAction getQualifierAction = new AccessTestAction() { 1514 @Override 1515 public Object run() throws Exception { 1516 Get g = new Get(TEST_ROW); 1517 g.addColumn(family1, qualifier); 1518 try (Connection conn = ConnectionFactory.createConnection(conf); 1519 Table t = conn.getTable(tableName)) { 1520 t.get(g); 1521 } 1522 return null; 1523 } 1524 }; 1525 1526 AccessTestAction putQualifierAction = new AccessTestAction() { 1527 @Override 1528 public Object run() throws Exception { 1529 Put p = new Put(TEST_ROW); 1530 p.addColumn(family1, qualifier, Bytes.toBytes("v1")); 1531 try (Connection conn = ConnectionFactory.createConnection(conf); 1532 Table t = conn.getTable(tableName)) { 1533 t.put(p); 1534 } 1535 return null; 1536 } 1537 }; 1538 1539 AccessTestAction deleteQualifierAction = new AccessTestAction() { 1540 @Override 1541 public Object run() throws Exception { 1542 Delete d = new Delete(TEST_ROW); 1543 d.addColumn(family1, qualifier); 1544 // d.deleteFamily(family1); 1545 try (Connection conn = ConnectionFactory.createConnection(conf); 1546 Table t = conn.getTable(tableName)) { 1547 t.delete(d); 1548 } 1549 return null; 1550 } 1551 }; 1552 1553 revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, null); 1554 1555 verifyDenied(user, getQualifierAction); 1556 verifyDenied(user, putQualifierAction); 1557 verifyDenied(user, deleteQualifierAction); 1558 1559 grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1560 Permission.Action.READ); 1561 1562 verifyAllowed(user, getQualifierAction); 1563 verifyDenied(user, putQualifierAction); 1564 verifyDenied(user, deleteQualifierAction); 1565 1566 // only grant write permission 1567 // TODO: comment this portion after HBASE-3583 1568 grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1569 Permission.Action.WRITE); 1570 1571 verifyDenied(user, getQualifierAction); 1572 verifyAllowed(user, putQualifierAction); 1573 verifyAllowed(user, deleteQualifierAction); 1574 1575 // grant both read and write permission 1576 grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1577 Permission.Action.READ, Permission.Action.WRITE); 1578 1579 verifyAllowed(user, getQualifierAction); 1580 verifyAllowed(user, putQualifierAction); 1581 verifyAllowed(user, deleteQualifierAction); 1582 1583 // revoke family level permission won't impact column level 1584 revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier); 1585 1586 verifyDenied(user, getQualifierAction); 1587 verifyDenied(user, putQualifierAction); 1588 verifyDenied(user, deleteQualifierAction); 1589 } finally { 1590 // delete table 1591 deleteTable(TEST_UTIL, tableName); 1592 } 1593 } 1594 1595 @Test 1596 public void testPermissionList() throws Exception { 1597 final TableName tableName = TableName.valueOf(name.getMethodName()); 1598 final byte[] family1 = Bytes.toBytes("f1"); 1599 final byte[] family2 = Bytes.toBytes("f2"); 1600 final byte[] qualifier = Bytes.toBytes("q"); 1601 1602 // create table 1603 Admin admin = TEST_UTIL.getAdmin(); 1604 if (admin.tableExists(tableName)) { 1605 deleteTable(TEST_UTIL, tableName); 1606 } 1607 HTableDescriptor htd = new HTableDescriptor(tableName); 1608 htd.addFamily(new HColumnDescriptor(family1)); 1609 htd.addFamily(new HColumnDescriptor(family2)); 1610 htd.setOwner(USER_OWNER); 1611 createTable(TEST_UTIL, htd); 1612 try { 1613 List<UserPermission> perms; 1614 Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1615 try { 1616 BlockingRpcChannel service = acl.coprocessorService(tableName.getName()); 1617 AccessControlService.BlockingInterface protocol = 1618 AccessControlService.newBlockingStub(service); 1619 perms = AccessControlUtil.getUserPermissions(null, protocol, tableName); 1620 } finally { 1621 acl.close(); 1622 } 1623 1624 UserPermission ownerperm = 1625 new UserPermission(Bytes.toBytes(USER_OWNER.getName()), tableName, null, Action.values()); 1626 assertTrue("Owner should have all permissions on table", 1627 hasFoundUserPermission(ownerperm, perms)); 1628 1629 User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]); 1630 byte[] userName = Bytes.toBytes(user.getShortName()); 1631 1632 UserPermission up = 1633 new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ); 1634 assertFalse("User should not be granted permission: " + up.toString(), 1635 hasFoundUserPermission(up, perms)); 1636 1637 // grant read permission 1638 grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1639 Permission.Action.READ); 1640 1641 acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1642 try { 1643 BlockingRpcChannel service = acl.coprocessorService(tableName.getName()); 1644 AccessControlService.BlockingInterface protocol = 1645 AccessControlService.newBlockingStub(service); 1646 perms = AccessControlUtil.getUserPermissions(null, protocol, tableName); 1647 } finally { 1648 acl.close(); 1649 } 1650 1651 UserPermission upToVerify = 1652 new UserPermission(userName, tableName, family1, qualifier, Permission.Action.READ); 1653 assertTrue("User should be granted permission: " + upToVerify.toString(), 1654 hasFoundUserPermission(upToVerify, perms)); 1655 1656 upToVerify = 1657 new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE); 1658 assertFalse("User should not be granted permission: " + upToVerify.toString(), 1659 hasFoundUserPermission(upToVerify, perms)); 1660 1661 // grant read+write 1662 grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1663 Permission.Action.WRITE, Permission.Action.READ); 1664 1665 acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1666 try { 1667 BlockingRpcChannel service = acl.coprocessorService(tableName.getName()); 1668 AccessControlService.BlockingInterface protocol = 1669 AccessControlService.newBlockingStub(service); 1670 perms = AccessControlUtil.getUserPermissions(null, protocol, tableName); 1671 } finally { 1672 acl.close(); 1673 } 1674 1675 upToVerify = 1676 new UserPermission(userName, tableName, family1, qualifier, Permission.Action.WRITE, 1677 Permission.Action.READ); 1678 assertTrue("User should be granted permission: " + upToVerify.toString(), 1679 hasFoundUserPermission(upToVerify, perms)); 1680 1681 // revoke 1682 revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier, 1683 Permission.Action.WRITE, Permission.Action.READ); 1684 1685 acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1686 try { 1687 BlockingRpcChannel service = acl.coprocessorService(tableName.getName()); 1688 AccessControlService.BlockingInterface protocol = 1689 AccessControlService.newBlockingStub(service); 1690 perms = AccessControlUtil.getUserPermissions(null, protocol, tableName); 1691 } finally { 1692 acl.close(); 1693 } 1694 1695 assertFalse("User should not be granted permission: " + upToVerify.toString(), 1696 hasFoundUserPermission(upToVerify, perms)); 1697 1698 // disable table before modification 1699 admin.disableTable(tableName); 1700 1701 User newOwner = User.createUserForTesting(conf, "new_owner", new String[] {}); 1702 htd.setOwner(newOwner); 1703 admin.modifyTable(tableName, htd); 1704 1705 acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1706 try { 1707 BlockingRpcChannel service = acl.coprocessorService(tableName.getName()); 1708 AccessControlService.BlockingInterface protocol = 1709 AccessControlService.newBlockingStub(service); 1710 perms = AccessControlUtil.getUserPermissions(null, protocol, tableName); 1711 } finally { 1712 acl.close(); 1713 } 1714 1715 UserPermission newOwnerperm = 1716 new UserPermission(Bytes.toBytes(newOwner.getName()), tableName, null, Action.values()); 1717 assertTrue("New owner should have all permissions on table", 1718 hasFoundUserPermission(newOwnerperm, perms)); 1719 } finally { 1720 // delete table 1721 deleteTable(TEST_UTIL, tableName); 1722 } 1723 } 1724 1725 @Test 1726 public void testGlobalPermissionList() throws Exception { 1727 List<UserPermission> perms; 1728 Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1729 try { 1730 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); 1731 AccessControlService.BlockingInterface protocol = 1732 AccessControlService.newBlockingStub(service); 1733 perms = AccessControlUtil.getUserPermissions(null, protocol); 1734 } finally { 1735 acl.close(); 1736 } 1737 1738 Collection<String> superUsers = Superusers.getSuperUsers(); 1739 List<UserPermission> adminPerms = new ArrayList<>(superUsers.size() + 1); 1740 adminPerms.add(new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()), 1741 AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"))); 1742 1743 for(String user: superUsers) { 1744 adminPerms.add(new UserPermission(Bytes.toBytes(user), AccessControlLists.ACL_TABLE_NAME, 1745 null, null, Action.values())); 1746 } 1747 assertTrue("Only super users, global users and user admin has permission on table hbase:acl " + 1748 "per setup", perms.size() == 5 + superUsers.size() && 1749 hasFoundUserPermission(adminPerms, perms)); 1750 } 1751 1752 /** global operations */ 1753 private void verifyGlobal(AccessTestAction action) throws Exception { 1754 verifyAllowed(action, SUPERUSER); 1755 1756 verifyDenied(action, USER_CREATE, USER_RW, USER_NONE, USER_RO); 1757 } 1758 1759 @Test 1760 public void testCheckPermissions() throws Exception { 1761 // -------------------------------------- 1762 // test global permissions 1763 AccessTestAction globalAdmin = new AccessTestAction() { 1764 @Override 1765 public Void run() throws Exception { 1766 checkGlobalPerms(TEST_UTIL, Permission.Action.ADMIN); 1767 return null; 1768 } 1769 }; 1770 // verify that only superuser can admin 1771 verifyGlobal(globalAdmin); 1772 1773 // -------------------------------------- 1774 // test multiple permissions 1775 AccessTestAction globalReadWrite = new AccessTestAction() { 1776 @Override 1777 public Void run() throws Exception { 1778 checkGlobalPerms(TEST_UTIL, Permission.Action.READ, Permission.Action.WRITE); 1779 return null; 1780 } 1781 }; 1782 1783 verifyGlobal(globalReadWrite); 1784 1785 // -------------------------------------- 1786 // table/column/qualifier level permissions 1787 final byte[] TEST_Q1 = Bytes.toBytes("q1"); 1788 final byte[] TEST_Q2 = Bytes.toBytes("q2"); 1789 1790 User userTable = User.createUserForTesting(conf, "user_check_perms_table", new String[0]); 1791 User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]); 1792 User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]); 1793 1794 grantOnTable(TEST_UTIL, userTable.getShortName(), 1795 TEST_TABLE, null, null, 1796 Permission.Action.READ); 1797 grantOnTable(TEST_UTIL, userColumn.getShortName(), 1798 TEST_TABLE, TEST_FAMILY, null, 1799 Permission.Action.READ); 1800 grantOnTable(TEST_UTIL, userQualifier.getShortName(), 1801 TEST_TABLE, TEST_FAMILY, TEST_Q1, 1802 Permission.Action.READ); 1803 1804 try { 1805 AccessTestAction tableRead = new AccessTestAction() { 1806 @Override 1807 public Void run() throws Exception { 1808 checkTablePerms(TEST_UTIL, TEST_TABLE, null, null, Permission.Action.READ); 1809 return null; 1810 } 1811 }; 1812 1813 AccessTestAction columnRead = new AccessTestAction() { 1814 @Override 1815 public Void run() throws Exception { 1816 checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ); 1817 return null; 1818 } 1819 }; 1820 1821 AccessTestAction qualifierRead = new AccessTestAction() { 1822 @Override 1823 public Void run() throws Exception { 1824 checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ); 1825 return null; 1826 } 1827 }; 1828 1829 AccessTestAction multiQualifierRead = new AccessTestAction() { 1830 @Override 1831 public Void run() throws Exception { 1832 checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] { 1833 new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ), 1834 new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q2, Permission.Action.READ), }); 1835 return null; 1836 } 1837 }; 1838 1839 AccessTestAction globalAndTableRead = new AccessTestAction() { 1840 @Override 1841 public Void run() throws Exception { 1842 checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] { 1843 new Permission(Permission.Action.READ), 1844 new TablePermission(TEST_TABLE, null, (byte[]) null, Permission.Action.READ), }); 1845 return null; 1846 } 1847 }; 1848 1849 AccessTestAction noCheck = new AccessTestAction() { 1850 @Override 1851 public Void run() throws Exception { 1852 checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[0]); 1853 return null; 1854 } 1855 }; 1856 1857 verifyAllowed(tableRead, SUPERUSER, userTable); 1858 verifyDenied(tableRead, userColumn, userQualifier); 1859 1860 verifyAllowed(columnRead, SUPERUSER, userTable, userColumn); 1861 verifyDenied(columnRead, userQualifier); 1862 1863 verifyAllowed(qualifierRead, SUPERUSER, userTable, userColumn, userQualifier); 1864 1865 verifyAllowed(multiQualifierRead, SUPERUSER, userTable, userColumn); 1866 verifyDenied(multiQualifierRead, userQualifier); 1867 1868 verifyAllowed(globalAndTableRead, SUPERUSER); 1869 verifyDenied(globalAndTableRead, userTable, userColumn, userQualifier); 1870 1871 verifyAllowed(noCheck, SUPERUSER, userTable, userColumn, userQualifier); 1872 1873 // -------------------------------------- 1874 // test family level multiple permissions 1875 AccessTestAction familyReadWrite = new AccessTestAction() { 1876 @Override 1877 public Void run() throws Exception { 1878 checkTablePerms(TEST_UTIL, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ, 1879 Permission.Action.WRITE); 1880 return null; 1881 } 1882 }; 1883 1884 verifyAllowed(familyReadWrite, SUPERUSER, USER_OWNER, USER_CREATE, USER_RW); 1885 verifyDenied(familyReadWrite, USER_NONE, USER_RO); 1886 1887 // -------------------------------------- 1888 // check for wrong table region 1889 CheckPermissionsRequest checkRequest = 1890 CheckPermissionsRequest 1891 .newBuilder() 1892 .addPermission( 1893 AccessControlProtos.Permission 1894 .newBuilder() 1895 .setType(AccessControlProtos.Permission.Type.Table) 1896 .setTablePermission( 1897 AccessControlProtos.TablePermission.newBuilder() 1898 .setTableName(ProtobufUtil.toProtoTableName(TEST_TABLE)) 1899 .addAction(AccessControlProtos.Permission.Action.CREATE))).build(); 1900 Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); 1901 try { 1902 BlockingRpcChannel channel = acl.coprocessorService(new byte[0]); 1903 AccessControlService.BlockingInterface protocol = 1904 AccessControlService.newBlockingStub(channel); 1905 try { 1906 // but ask for TablePermissions for TEST_TABLE 1907 protocol.checkPermissions(null, checkRequest); 1908 fail("this should have thrown CoprocessorException"); 1909 } catch (ServiceException ex) { 1910 // expected 1911 } 1912 } finally { 1913 acl.close(); 1914 } 1915 1916 } finally { 1917 revokeFromTable(TEST_UTIL, userTable.getShortName(), TEST_TABLE, null, null, 1918 Permission.Action.READ); 1919 revokeFromTable(TEST_UTIL, userColumn.getShortName(), TEST_TABLE, TEST_FAMILY, null, 1920 Permission.Action.READ); 1921 revokeFromTable(TEST_UTIL, userQualifier.getShortName(), TEST_TABLE, TEST_FAMILY, TEST_Q1, 1922 Permission.Action.READ); 1923 } 1924 } 1925 1926 @Test 1927 public void testStopRegionServer() throws Exception { 1928 AccessTestAction action = new AccessTestAction() { 1929 @Override 1930 public Object run() throws Exception { 1931 ACCESS_CONTROLLER.preStopRegionServer(ObserverContextImpl.createAndPrepare(RSCP_ENV)); 1932 return null; 1933 } 1934 }; 1935 1936 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 1937 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 1938 USER_GROUP_WRITE, USER_GROUP_CREATE); 1939 } 1940 1941 @Test 1942 public void testRollWALWriterRequest() throws Exception { 1943 AccessTestAction action = new AccessTestAction() { 1944 @Override 1945 public Object run() throws Exception { 1946 ACCESS_CONTROLLER.preRollWALWriterRequest(ObserverContextImpl.createAndPrepare(RSCP_ENV)); 1947 return null; 1948 } 1949 }; 1950 1951 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 1952 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 1953 USER_GROUP_WRITE, USER_GROUP_CREATE); 1954 } 1955 1956 @Test 1957 public void testOpenRegion() throws Exception { 1958 AccessTestAction action = new AccessTestAction() { 1959 @Override 1960 public Object run() throws Exception { 1961 ACCESS_CONTROLLER.preOpen(ObserverContextImpl.createAndPrepare(RCP_ENV)); 1962 return null; 1963 } 1964 }; 1965 1966 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 1967 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_CREATE, 1968 USER_GROUP_READ, USER_GROUP_WRITE); 1969 } 1970 1971 @Test 1972 public void testCloseRegion() throws Exception { 1973 AccessTestAction action = new AccessTestAction() { 1974 @Override 1975 public Object run() throws Exception { 1976 ACCESS_CONTROLLER.preClose(ObserverContextImpl.createAndPrepare(RCP_ENV), false); 1977 return null; 1978 } 1979 }; 1980 1981 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 1982 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_GROUP_CREATE, 1983 USER_GROUP_READ, USER_GROUP_WRITE); 1984 } 1985 1986 @Test 1987 public void testSnapshot() throws Exception { 1988 Admin admin = TEST_UTIL.getAdmin(); 1989 final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE); 1990 final SnapshotDescription snapshot = new SnapshotDescription( 1991 TEST_TABLE.getNameAsString() + "-snapshot", TEST_TABLE); 1992 AccessTestAction snapshotAction = new AccessTestAction() { 1993 @Override 1994 public Object run() throws Exception { 1995 ACCESS_CONTROLLER.preSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 1996 snapshot, htd); 1997 return null; 1998 } 1999 }; 2000 2001 AccessTestAction deleteAction = new AccessTestAction() { 2002 @Override 2003 public Object run() throws Exception { 2004 ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2005 snapshot); 2006 return null; 2007 } 2008 }; 2009 2010 AccessTestAction restoreAction = new AccessTestAction() { 2011 @Override 2012 public Object run() throws Exception { 2013 ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2014 snapshot, htd); 2015 return null; 2016 } 2017 }; 2018 2019 AccessTestAction cloneAction = new AccessTestAction() { 2020 @Override 2021 public Object run() throws Exception { 2022 ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2023 snapshot, null); 2024 return null; 2025 } 2026 }; 2027 2028 verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2029 verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2030 USER_GROUP_WRITE, USER_GROUP_CREATE); 2031 2032 verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2033 verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2034 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2035 2036 verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2037 verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2038 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2039 2040 verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2041 verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2042 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2043 } 2044 2045 @Test 2046 public void testSnapshotWithOwner() throws Exception { 2047 Admin admin = TEST_UTIL.getAdmin(); 2048 final HTableDescriptor htd = admin.getTableDescriptor(TEST_TABLE); 2049 final SnapshotDescription snapshot = new SnapshotDescription( 2050 TEST_TABLE.getNameAsString() + "-snapshot", TEST_TABLE, null, USER_OWNER.getName()); 2051 2052 AccessTestAction snapshotAction = new AccessTestAction() { 2053 @Override 2054 public Object run() throws Exception { 2055 ACCESS_CONTROLLER.preSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2056 snapshot, htd); 2057 return null; 2058 } 2059 }; 2060 verifyAllowed(snapshotAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2061 verifyDenied(snapshotAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2062 USER_GROUP_WRITE, USER_GROUP_CREATE); 2063 2064 AccessTestAction deleteAction = new AccessTestAction() { 2065 @Override 2066 public Object run() throws Exception { 2067 ACCESS_CONTROLLER.preDeleteSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2068 snapshot); 2069 return null; 2070 } 2071 }; 2072 verifyAllowed(deleteAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2073 verifyDenied(deleteAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2074 USER_GROUP_WRITE, USER_GROUP_CREATE); 2075 2076 AccessTestAction restoreAction = new AccessTestAction() { 2077 @Override 2078 public Object run() throws Exception { 2079 ACCESS_CONTROLLER.preRestoreSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2080 snapshot, htd); 2081 return null; 2082 } 2083 }; 2084 verifyAllowed(restoreAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2085 verifyDenied(restoreAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2086 USER_GROUP_WRITE, USER_GROUP_CREATE); 2087 2088 AccessTestAction cloneAction = new AccessTestAction() { 2089 @Override 2090 public Object run() throws Exception { 2091 ACCESS_CONTROLLER.preCloneSnapshot(ObserverContextImpl.createAndPrepare(CP_ENV), 2092 snapshot, htd); 2093 return null; 2094 } 2095 }; 2096 verifyAllowed(cloneAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER); 2097 verifyDenied(cloneAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2098 USER_GROUP_WRITE, USER_GROUP_CREATE); 2099 } 2100 2101 @Test 2102 public void testGlobalAuthorizationForNewRegisteredRS() throws Exception { 2103 LOG.debug("Test for global authorization for a new registered RegionServer."); 2104 MiniHBaseCluster hbaseCluster = TEST_UTIL.getHBaseCluster(); 2105 2106 final Admin admin = TEST_UTIL.getAdmin(); 2107 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE2); 2108 htd.addFamily(new HColumnDescriptor(TEST_FAMILY)); 2109 createTable(TEST_UTIL, htd); 2110 2111 // Starting a new RegionServer. 2112 JVMClusterUtil.RegionServerThread newRsThread = hbaseCluster 2113 .startRegionServer(); 2114 final HRegionServer newRs = newRsThread.getRegionServer(); 2115 2116 // Move region to the new RegionServer. 2117 List<HRegionLocation> regions; 2118 try (RegionLocator locator = systemUserConnection.getRegionLocator(TEST_TABLE2)) { 2119 regions = locator.getAllRegionLocations(); 2120 } 2121 HRegionLocation location = regions.get(0); 2122 final HRegionInfo hri = location.getRegionInfo(); 2123 final ServerName server = location.getServerName(); 2124 try (Table table = systemUserConnection.getTable(TEST_TABLE2)) { 2125 AccessTestAction moveAction = new AccessTestAction() { 2126 @Override 2127 public Object run() throws Exception { 2128 admin.move(hri.getEncodedNameAsBytes(), 2129 Bytes.toBytes(newRs.getServerName().getServerName())); 2130 return null; 2131 } 2132 }; 2133 SUPERUSER.runAs(moveAction); 2134 2135 final int RETRIES_LIMIT = 10; 2136 int retries = 0; 2137 while (newRs.getRegions(TEST_TABLE2).size() < 1 && retries < RETRIES_LIMIT) { 2138 LOG.debug("Waiting for region to be opened. Already retried " + retries 2139 + " times."); 2140 try { 2141 Thread.sleep(1000); 2142 } catch (InterruptedException e) { 2143 } 2144 retries++; 2145 if (retries == RETRIES_LIMIT - 1) { 2146 fail("Retry exhaust for waiting region to be opened."); 2147 } 2148 } 2149 // Verify write permission for user "admin2" who has the global 2150 // permissions. 2151 AccessTestAction putAction = new AccessTestAction() { 2152 @Override 2153 public Object run() throws Exception { 2154 Put put = new Put(Bytes.toBytes("test")); 2155 put.addColumn(TEST_FAMILY, Bytes.toBytes("qual"), Bytes.toBytes("value")); 2156 table.put(put); 2157 return null; 2158 } 2159 }; 2160 USER_ADMIN.runAs(putAction); 2161 } 2162 } 2163 2164 @Test 2165 public void testTableDescriptorsEnumeration() throws Exception { 2166 User TABLE_ADMIN = User.createUserForTesting(conf, "UserA", new String[0]); 2167 2168 // Grant TABLE ADMIN privs 2169 grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(), TEST_TABLE, null, null, 2170 Permission.Action.ADMIN); 2171 try { 2172 AccessTestAction listTablesAction = new AccessTestAction() { 2173 @Override 2174 public Object run() throws Exception { 2175 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()); 2176 Admin admin = conn.getAdmin()) { 2177 return Arrays.asList(admin.listTables()); 2178 } 2179 } 2180 }; 2181 2182 AccessTestAction getTableDescAction = new AccessTestAction() { 2183 @Override 2184 public Object run() throws Exception { 2185 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()); 2186 Admin admin = conn.getAdmin();) { 2187 return admin.getTableDescriptor(TEST_TABLE); 2188 } 2189 } 2190 }; 2191 2192 verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, TABLE_ADMIN, 2193 USER_GROUP_CREATE, USER_GROUP_ADMIN); 2194 verifyIfEmptyList(listTablesAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2195 USER_GROUP_WRITE); 2196 2197 verifyAllowed(getTableDescAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, 2198 TABLE_ADMIN, USER_GROUP_CREATE, USER_GROUP_ADMIN); 2199 verifyDenied(getTableDescAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2200 USER_GROUP_WRITE); 2201 } finally { 2202 // Cleanup, revoke TABLE ADMIN privs 2203 revokeFromTable(TEST_UTIL, TABLE_ADMIN.getShortName(), TEST_TABLE, null, null, 2204 Permission.Action.ADMIN); 2205 } 2206 } 2207 2208 @Test 2209 public void testTableNameEnumeration() throws Exception { 2210 AccessTestAction listTablesAction = new AccessTestAction() { 2211 @Override 2212 public Object run() throws Exception { 2213 Connection unmanagedConnection = 2214 ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()); 2215 Admin admin = unmanagedConnection.getAdmin(); 2216 try { 2217 return Arrays.asList(admin.listTableNames()); 2218 } finally { 2219 admin.close(); 2220 unmanagedConnection.close(); 2221 } 2222 } 2223 }; 2224 2225 verifyAllowed(listTablesAction, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_RW, 2226 USER_RO, USER_GROUP_CREATE, USER_GROUP_ADMIN, USER_GROUP_READ, USER_GROUP_WRITE); 2227 verifyIfEmptyList(listTablesAction, USER_NONE); 2228 } 2229 2230 @Test 2231 public void testTableDeletion() throws Exception { 2232 User TABLE_ADMIN = User.createUserForTesting(conf, "TestUser", new String[0]); 2233 final TableName tableName = TableName.valueOf(name.getMethodName()); 2234 createTestTable(tableName); 2235 2236 // Grant TABLE ADMIN privs 2237 grantOnTable(TEST_UTIL, TABLE_ADMIN.getShortName(), tableName, null, null, Permission.Action.ADMIN); 2238 2239 AccessTestAction deleteTableAction = new AccessTestAction() { 2240 @Override 2241 public Object run() throws Exception { 2242 Connection unmanagedConnection = 2243 ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()); 2244 Admin admin = unmanagedConnection.getAdmin(); 2245 try { 2246 deleteTable(TEST_UTIL, admin, tableName); 2247 } finally { 2248 admin.close(); 2249 unmanagedConnection.close(); 2250 } 2251 return null; 2252 } 2253 }; 2254 2255 verifyDenied(deleteTableAction, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, 2256 USER_GROUP_WRITE); 2257 verifyAllowed(deleteTableAction, TABLE_ADMIN); 2258 } 2259 2260 private void createTestTable(TableName tname) throws Exception { 2261 HTableDescriptor htd = new HTableDescriptor(tname); 2262 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY); 2263 hcd.setMaxVersions(100); 2264 htd.addFamily(hcd); 2265 htd.setOwner(USER_OWNER); 2266 createTable(TEST_UTIL, htd, new byte[][] { Bytes.toBytes("s") }); 2267 } 2268 2269 @Test 2270 public void testNamespaceUserGrant() throws Exception { 2271 AccessTestAction getAction = new AccessTestAction() { 2272 @Override 2273 public Object run() throws Exception { 2274 try(Connection conn = ConnectionFactory.createConnection(conf); 2275 Table t = conn.getTable(TEST_TABLE);) { 2276 return t.get(new Get(TEST_ROW)); 2277 } 2278 } 2279 }; 2280 2281 String namespace = TEST_TABLE.getNamespaceAsString(); 2282 2283 // Grant namespace READ to USER_NONE, this should supersede any table permissions 2284 grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ); 2285 // Now USER_NONE should be able to read 2286 verifyAllowed(getAction, USER_NONE); 2287 2288 // Revoke namespace READ to USER_NONE 2289 revokeFromNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ); 2290 verifyDenied(getAction, USER_NONE); 2291 } 2292 2293 @Test 2294 public void testAccessControlClientGrantRevoke() throws Exception { 2295 // Create user for testing, who has no READ privileges by default. 2296 User testGrantRevoke = User.createUserForTesting(conf, "testGrantRevoke", new String[0]); 2297 AccessTestAction getAction = new AccessTestAction() { 2298 @Override 2299 public Object run() throws Exception { 2300 try(Connection conn = ConnectionFactory.createConnection(conf); 2301 Table t = conn.getTable(TEST_TABLE);) { 2302 return t.get(new Get(TEST_ROW)); 2303 } 2304 } 2305 }; 2306 2307 verifyDenied(getAction, testGrantRevoke); 2308 2309 // Grant table READ permissions to testGrantRevoke. 2310 try { 2311 grantOnTableUsingAccessControlClient(TEST_UTIL, systemUserConnection, 2312 testGrantRevoke.getShortName(), TEST_TABLE, null, null, Permission.Action.READ); 2313 } catch (Throwable e) { 2314 LOG.error("error during call of AccessControlClient.grant. ", e); 2315 } 2316 2317 // Now testGrantRevoke should be able to read also 2318 verifyAllowed(getAction, testGrantRevoke); 2319 2320 // Revoke table READ permission to testGrantRevoke. 2321 try { 2322 revokeFromTableUsingAccessControlClient(TEST_UTIL, systemUserConnection, 2323 testGrantRevoke.getShortName(), TEST_TABLE, null, null, Permission.Action.READ); 2324 } catch (Throwable e) { 2325 LOG.error("error during call of AccessControlClient.revoke ", e); 2326 } 2327 2328 // Now testGrantRevoke shouldn't be able read 2329 verifyDenied(getAction, testGrantRevoke); 2330 } 2331 2332 @Test 2333 public void testAccessControlClientGlobalGrantRevoke() throws Exception { 2334 // Create user for testing, who has no READ privileges by default. 2335 User testGlobalGrantRevoke = User.createUserForTesting(conf, 2336 "testGlobalGrantRevoke", new String[0]); 2337 AccessTestAction getAction = new AccessTestAction() { 2338 @Override 2339 public Object run() throws Exception { 2340 try(Connection conn = ConnectionFactory.createConnection(conf); 2341 Table t = conn.getTable(TEST_TABLE)) { 2342 return t.get(new Get(TEST_ROW)); 2343 } 2344 } 2345 }; 2346 2347 verifyDenied(getAction, testGlobalGrantRevoke); 2348 2349 // Grant table READ permissions to testGlobalGrantRevoke. 2350 String userName = testGlobalGrantRevoke.getShortName(); 2351 try { 2352 grantGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2353 Permission.Action.READ); 2354 } catch (Throwable e) { 2355 LOG.error("error during call of AccessControlClient.grant. ", e); 2356 } 2357 try { 2358 // Now testGlobalGrantRevoke should be able to read also 2359 verifyAllowed(getAction, testGlobalGrantRevoke); 2360 } catch (Exception e) { 2361 revokeGlobal(TEST_UTIL, userName, Permission.Action.READ); 2362 throw e; 2363 } 2364 2365 // Revoke table READ permission to testGlobalGrantRevoke. 2366 try { 2367 revokeGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2368 Permission.Action.READ); 2369 } catch (Throwable e) { 2370 LOG.error("error during call of AccessControlClient.revoke ", e); 2371 } 2372 2373 // Now testGlobalGrantRevoke shouldn't be able read 2374 verifyDenied(getAction, testGlobalGrantRevoke); 2375 2376 } 2377 2378 @Test 2379 public void testAccessControlClientMultiGrantRevoke() throws Exception { 2380 User testGrantRevoke = 2381 User.createUserForTesting(conf, "testGrantRevoke", new String[0]); 2382 AccessTestAction getAction = new AccessTestAction() { 2383 @Override 2384 public Object run() throws Exception { 2385 try(Connection conn = ConnectionFactory.createConnection(conf); 2386 Table t = conn.getTable(TEST_TABLE)) { 2387 return t.get(new Get(TEST_ROW)); 2388 } 2389 } 2390 }; 2391 2392 AccessTestAction putAction = new AccessTestAction() { 2393 @Override 2394 public Object run() throws Exception { 2395 Put p = new Put(TEST_ROW); 2396 p.addColumn(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1)); 2397 try(Connection conn = ConnectionFactory.createConnection(conf); 2398 Table t = conn.getTable(TEST_TABLE)) { 2399 t.put(p); 2400 return null; 2401 } 2402 } 2403 }; 2404 2405 verifyDenied(getAction, testGrantRevoke); 2406 verifyDenied(putAction, testGrantRevoke); 2407 2408 // Grant global READ permissions to testGrantRevoke. 2409 String userName = testGrantRevoke.getShortName(); 2410 try { 2411 grantGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2412 Permission.Action.READ); 2413 } catch (Throwable e) { 2414 LOG.error("error during call of AccessControlClient.grant. ", e); 2415 } 2416 verifyAllowed(getAction, testGrantRevoke); 2417 verifyDenied(putAction, testGrantRevoke); 2418 2419 // Grant global READ permissions to testGrantRevoke. 2420 try { 2421 grantGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2422 Permission.Action.WRITE); 2423 } catch (Throwable e) { 2424 LOG.error("error during call of AccessControlClient.grant. ", e); 2425 } 2426 verifyAllowed(getAction, testGrantRevoke); 2427 verifyAllowed(putAction, testGrantRevoke); 2428 2429 // Revoke global READ permission to testGrantRevoke. 2430 try { 2431 revokeGlobalUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2432 Permission.Action.READ, Permission.Action.WRITE); 2433 } catch (Throwable e) { 2434 LOG.error("error during call of AccessControlClient.revoke ", e); 2435 } 2436 verifyDenied(getAction, testGrantRevoke); 2437 verifyDenied(putAction, testGrantRevoke); 2438 2439 // Grant table READ & WRITE permissions to testGrantRevoke 2440 try { 2441 grantOnTableUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, TEST_TABLE, 2442 null, null, Permission.Action.READ); 2443 } catch (Throwable e) { 2444 LOG.error("error during call of AccessControlClient.grant. ", e); 2445 } 2446 verifyAllowed(getAction, testGrantRevoke); 2447 verifyDenied(putAction, testGrantRevoke); 2448 2449 // Grant table WRITE permissions to testGrantRevoke 2450 try { 2451 grantOnTableUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, TEST_TABLE, 2452 null, null, Action.WRITE); 2453 } catch (Throwable e) { 2454 LOG.error("error during call of AccessControlClient.grant. ", e); 2455 } 2456 verifyAllowed(getAction, testGrantRevoke); 2457 verifyAllowed(putAction, testGrantRevoke); 2458 2459 // Revoke table READ & WRITE permission to testGrantRevoke. 2460 try { 2461 revokeFromTableUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, TEST_TABLE, null, null, 2462 Permission.Action.READ, Permission.Action.WRITE); 2463 } catch (Throwable e) { 2464 LOG.error("error during call of AccessControlClient.revoke ", e); 2465 } 2466 verifyDenied(getAction, testGrantRevoke); 2467 verifyDenied(putAction, testGrantRevoke); 2468 2469 // Grant Namespace READ permissions to testGrantRevoke 2470 String namespace = TEST_TABLE.getNamespaceAsString(); 2471 try { 2472 grantOnNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2473 namespace, Permission.Action.READ); 2474 } catch (Throwable e) { 2475 LOG.error("error during call of AccessControlClient.grant. ", e); 2476 } 2477 verifyAllowed(getAction, testGrantRevoke); 2478 verifyDenied(putAction, testGrantRevoke); 2479 2480 // Grant Namespace WRITE permissions to testGrantRevoke 2481 try { 2482 grantOnNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2483 namespace, Permission.Action.WRITE); 2484 } catch (Throwable e) { 2485 LOG.error("error during call of AccessControlClient.grant. ", e); 2486 } 2487 verifyAllowed(getAction, testGrantRevoke); 2488 verifyAllowed(putAction, testGrantRevoke); 2489 2490 // Revoke table READ & WRITE permission to testGrantRevoke. 2491 try { 2492 revokeFromNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2493 TEST_TABLE.getNamespaceAsString(), Permission.Action.READ, Permission.Action.WRITE); 2494 } catch (Throwable e) { 2495 LOG.error("error during call of AccessControlClient.revoke ", e); 2496 } 2497 verifyDenied(getAction, testGrantRevoke); 2498 verifyDenied(putAction, testGrantRevoke); 2499 } 2500 2501 @Test 2502 public void testAccessControlClientGrantRevokeOnNamespace() throws Exception { 2503 // Create user for testing, who has no READ privileges by default. 2504 User testNS = User.createUserForTesting(conf, "testNS", new String[0]); 2505 AccessTestAction getAction = new AccessTestAction() { 2506 @Override 2507 public Object run() throws Exception { 2508 try(Connection conn = ConnectionFactory.createConnection(conf); 2509 Table t = conn.getTable(TEST_TABLE);) { 2510 return t.get(new Get(TEST_ROW)); 2511 } 2512 } 2513 }; 2514 2515 verifyDenied(getAction, testNS); 2516 2517 String userName = testNS.getShortName(); 2518 String namespace = TEST_TABLE.getNamespaceAsString(); 2519 // Grant namespace READ to testNS, this should supersede any table permissions 2520 try { 2521 grantOnNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, namespace, 2522 Permission.Action.READ); 2523 } catch (Throwable e) { 2524 LOG.error("error during call of AccessControlClient.grant. ", e); 2525 } 2526 try { 2527 // Now testNS should be able to read also 2528 verifyAllowed(getAction, testNS); 2529 } catch (Exception e) { 2530 revokeFromNamespace(TEST_UTIL, userName, namespace, Permission.Action.READ); 2531 throw e; 2532 } 2533 2534 // Revoke namespace READ to testNS, this should supersede any table permissions 2535 try { 2536 revokeFromNamespaceUsingAccessControlClient(TEST_UTIL, systemUserConnection, userName, 2537 namespace, Permission.Action.READ); 2538 } catch (Throwable e) { 2539 LOG.error("error during call of AccessControlClient.revoke ", e); 2540 } 2541 2542 // Now testNS shouldn't be able read 2543 verifyDenied(getAction, testNS); 2544 } 2545 2546 2547 public static class PingCoprocessor extends PingService implements RegionCoprocessor { 2548 2549 @Override 2550 public void start(CoprocessorEnvironment env) throws IOException { } 2551 2552 @Override 2553 public void stop(CoprocessorEnvironment env) throws IOException { } 2554 2555 @Override 2556 public Iterable<Service> getServices() { 2557 return Collections.singleton(this); 2558 } 2559 2560 @Override 2561 public void ping(RpcController controller, PingRequest request, 2562 RpcCallback<PingResponse> callback) { 2563 callback.run(PingResponse.newBuilder().setPong("Pong!").build()); 2564 } 2565 2566 @Override 2567 public void count(RpcController controller, CountRequest request, 2568 RpcCallback<CountResponse> callback) { 2569 callback.run(CountResponse.newBuilder().build()); 2570 } 2571 2572 @Override 2573 public void increment(RpcController controller, IncrementCountRequest requet, 2574 RpcCallback<IncrementCountResponse> callback) { 2575 callback.run(IncrementCountResponse.newBuilder().build()); 2576 } 2577 2578 @Override 2579 public void hello(RpcController controller, HelloRequest request, 2580 RpcCallback<HelloResponse> callback) { 2581 callback.run(HelloResponse.newBuilder().setResponse("Hello!").build()); 2582 } 2583 2584 @Override 2585 public void noop(RpcController controller, NoopRequest request, 2586 RpcCallback<NoopResponse> callback) { 2587 callback.run(NoopResponse.newBuilder().build()); 2588 } 2589 } 2590 2591 @Test 2592 public void testCoprocessorExec() throws Exception { 2593 // Set up our ping endpoint service on all regions of our test table 2594 for (JVMClusterUtil.RegionServerThread thread: 2595 TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) { 2596 HRegionServer rs = thread.getRegionServer(); 2597 for (HRegion region: rs.getRegions(TEST_TABLE)) { 2598 region.getCoprocessorHost().load(PingCoprocessor.class, 2599 Coprocessor.PRIORITY_USER, conf); 2600 } 2601 } 2602 2603 // Create users for testing, and grant EXEC privileges on our test table 2604 // only to user A 2605 User userA = User.createUserForTesting(conf, "UserA", new String[0]); 2606 User userB = User.createUserForTesting(conf, "UserB", new String[0]); 2607 2608 grantOnTable(TEST_UTIL, userA.getShortName(), 2609 TEST_TABLE, null, null, 2610 Permission.Action.EXEC); 2611 try { 2612 // Create an action for invoking our test endpoint 2613 AccessTestAction execEndpointAction = new AccessTestAction() { 2614 @Override 2615 public Object run() throws Exception { 2616 try (Connection conn = ConnectionFactory.createConnection(conf); 2617 Table t = conn.getTable(TEST_TABLE);) { 2618 BlockingRpcChannel service = t.coprocessorService(HConstants.EMPTY_BYTE_ARRAY); 2619 PingCoprocessor.newBlockingStub(service).noop(null, NoopRequest.newBuilder().build()); 2620 } 2621 return null; 2622 } 2623 }; 2624 2625 String namespace = TEST_TABLE.getNamespaceAsString(); 2626 // Now grant EXEC to the entire namespace to user B 2627 grantOnNamespace(TEST_UTIL, userB.getShortName(), namespace, Permission.Action.EXEC); 2628 // User B should now be allowed also 2629 verifyAllowed(execEndpointAction, userA, userB); 2630 2631 revokeFromNamespace(TEST_UTIL, userB.getShortName(), namespace, Permission.Action.EXEC); 2632 // Verify that EXEC permission is checked correctly 2633 verifyDenied(execEndpointAction, userB); 2634 verifyAllowed(execEndpointAction, userA); 2635 } finally { 2636 // Cleanup, revoke the userA privileges 2637 revokeFromTable(TEST_UTIL, userA.getShortName(), TEST_TABLE, null, null, 2638 Permission.Action.EXEC); 2639 } 2640 } 2641 2642 @Test 2643 public void testSetQuota() throws Exception { 2644 AccessTestAction setUserQuotaAction = new AccessTestAction() { 2645 @Override 2646 public Object run() throws Exception { 2647 ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV), 2648 null, null); 2649 return null; 2650 } 2651 }; 2652 2653 AccessTestAction setUserTableQuotaAction = new AccessTestAction() { 2654 @Override 2655 public Object run() throws Exception { 2656 ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV), null, 2657 TEST_TABLE, null); 2658 return null; 2659 } 2660 }; 2661 2662 AccessTestAction setUserNamespaceQuotaAction = new AccessTestAction() { 2663 @Override 2664 public Object run() throws Exception { 2665 ACCESS_CONTROLLER.preSetUserQuota(ObserverContextImpl.createAndPrepare(CP_ENV), 2666 null, (String)null, null); 2667 return null; 2668 } 2669 }; 2670 2671 AccessTestAction setTableQuotaAction = new AccessTestAction() { 2672 @Override 2673 public Object run() throws Exception { 2674 ACCESS_CONTROLLER.preSetTableQuota(ObserverContextImpl.createAndPrepare(CP_ENV), 2675 TEST_TABLE, null); 2676 return null; 2677 } 2678 }; 2679 2680 AccessTestAction setNamespaceQuotaAction = new AccessTestAction() { 2681 @Override 2682 public Object run() throws Exception { 2683 ACCESS_CONTROLLER.preSetNamespaceQuota(ObserverContextImpl.createAndPrepare(CP_ENV), 2684 null, null); 2685 return null; 2686 } 2687 }; 2688 2689 verifyAllowed(setUserQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2690 verifyDenied(setUserQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2691 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2692 2693 verifyAllowed(setUserTableQuotaAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2694 verifyDenied(setUserTableQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, 2695 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2696 2697 verifyAllowed(setUserNamespaceQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2698 verifyDenied(setUserNamespaceQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2699 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2700 2701 verifyAllowed(setTableQuotaAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); 2702 verifyDenied(setTableQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE); 2703 2704 verifyAllowed(setNamespaceQuotaAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 2705 verifyDenied(setNamespaceQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2706 USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 2707 } 2708 2709 @Test 2710 public void testGetNamespacePermission() throws Exception { 2711 String namespace = "testGetNamespacePermission"; 2712 NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build(); 2713 createNamespace(TEST_UTIL, desc); 2714 grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ); 2715 2716 // Test 1: A specific namespace 2717 getNamespacePermissionsAndVerify(namespace, 1, namespace); 2718 2719 // Test 2: '@.*' 2720 getNamespacePermissionsAndVerify(".*", 1, namespace); 2721 2722 // Test 3: A more complex regex 2723 getNamespacePermissionsAndVerify("^test[a-zA-Z]*", 1, namespace); 2724 2725 deleteNamespace(TEST_UTIL, namespace); 2726 } 2727 2728 /** 2729 * List all user permissions match the given regular expression for namespace 2730 * and verify each of them. 2731 * @param namespaceRegexWithoutPrefix the regualar expression for namespace, without NAMESPACE_PREFIX 2732 * @param expectedAmount the expected amount of user permissions returned 2733 * @param expectedNamespace the expected namespace of each user permission returned 2734 * @throws HBaseException in the case of any HBase exception when accessing hbase:acl table 2735 */ 2736 private void getNamespacePermissionsAndVerify(String namespaceRegexWithoutPrefix, 2737 int expectedAmount, String expectedNamespace) throws HBaseException { 2738 try { 2739 List<UserPermission> namespacePermissions = AccessControlClient.getUserPermissions( 2740 systemUserConnection, AccessControlLists.toNamespaceEntry(namespaceRegexWithoutPrefix)); 2741 assertTrue(namespacePermissions != null); 2742 assertEquals(expectedAmount, namespacePermissions.size()); 2743 for (UserPermission namespacePermission : namespacePermissions) { 2744 assertFalse(namespacePermission.isGlobal()); // Verify it is not a global user permission 2745 assertEquals(expectedNamespace, namespacePermission.getNamespace()); // Verify namespace is set 2746 } 2747 } catch (Throwable thw) { 2748 throw new HBaseException(thw); 2749 } 2750 } 2751 2752 @Test 2753 public void testTruncatePerms() throws Exception { 2754 try { 2755 List<UserPermission> existingPerms = AccessControlClient.getUserPermissions( 2756 systemUserConnection, TEST_TABLE.getNameAsString()); 2757 assertTrue(existingPerms != null); 2758 assertTrue(existingPerms.size() > 1); 2759 TEST_UTIL.getAdmin().disableTable(TEST_TABLE); 2760 TEST_UTIL.truncateTable(TEST_TABLE); 2761 TEST_UTIL.waitTableAvailable(TEST_TABLE); 2762 List<UserPermission> perms = AccessControlClient.getUserPermissions( 2763 systemUserConnection, TEST_TABLE.getNameAsString()); 2764 assertTrue(perms != null); 2765 assertEquals(existingPerms.size(), perms.size()); 2766 } catch (Throwable e) { 2767 throw new HBaseIOException(e); 2768 } 2769 } 2770 2771 private PrivilegedAction<List<UserPermission>> getPrivilegedAction(final String regex) { 2772 return new PrivilegedAction<List<UserPermission>>() { 2773 @Override 2774 public List<UserPermission> run() { 2775 try(Connection conn = ConnectionFactory.createConnection(conf);) { 2776 return AccessControlClient.getUserPermissions(conn, regex); 2777 } catch (Throwable e) { 2778 LOG.error("error during call of AccessControlClient.getUserPermissions.", e); 2779 return null; 2780 } 2781 } 2782 }; 2783 } 2784 2785 @Test 2786 public void testAccessControlClientUserPerms() throws Exception { 2787 final TableName tableName = TableName.valueOf(name.getMethodName()); 2788 createTestTable(tableName); 2789 try { 2790 final String regex = tableName.getNameWithNamespaceInclAsString(); 2791 User testUserPerms = User.createUserForTesting(conf, "testUserPerms", new String[0]); 2792 assertEquals(0, testUserPerms.runAs(getPrivilegedAction(regex)).size()); 2793 // Grant TABLE ADMIN privs to testUserPerms 2794 grantOnTable(TEST_UTIL, testUserPerms.getShortName(), tableName, null, null, Action.ADMIN); 2795 List<UserPermission> perms = testUserPerms.runAs(getPrivilegedAction(regex)); 2796 assertNotNull(perms); 2797 // Superuser, testUserPerms 2798 assertEquals(2, perms.size()); 2799 } finally { 2800 deleteTable(TEST_UTIL, tableName); 2801 } 2802 } 2803 2804 @Test 2805 public void testAccessControllerUserPermsRegexHandling() throws Exception { 2806 User testRegexHandler = User.createUserForTesting(conf, "testRegexHandling", new String[0]); 2807 2808 final String REGEX_ALL_TABLES = ".*"; 2809 final String tableName = name.getMethodName(); 2810 final TableName table1 = TableName.valueOf(tableName); 2811 final byte[] family = Bytes.toBytes("f1"); 2812 2813 // create table in default ns 2814 Admin admin = TEST_UTIL.getAdmin(); 2815 HTableDescriptor htd = new HTableDescriptor(table1); 2816 htd.addFamily(new HColumnDescriptor(family)); 2817 createTable(TEST_UTIL, htd); 2818 2819 // creating the ns and table in it 2820 String ns = "testNamespace"; 2821 NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build(); 2822 final TableName table2 = TableName.valueOf(ns, tableName); 2823 createNamespace(TEST_UTIL, desc); 2824 htd = new HTableDescriptor(table2); 2825 htd.addFamily(new HColumnDescriptor(family)); 2826 createTable(TEST_UTIL, htd); 2827 2828 // Verify that we can read sys-tables 2829 String aclTableName = AccessControlLists.ACL_TABLE_NAME.getNameAsString(); 2830 assertEquals(5, SUPERUSER.runAs(getPrivilegedAction(aclTableName)).size()); 2831 assertEquals(0, testRegexHandler.runAs(getPrivilegedAction(aclTableName)).size()); 2832 2833 // Grant TABLE ADMIN privs to testUserPerms 2834 assertEquals(0, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size()); 2835 grantOnTable(TEST_UTIL, testRegexHandler.getShortName(), table1, null, null, Action.ADMIN); 2836 assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size()); 2837 grantOnTable(TEST_UTIL, testRegexHandler.getShortName(), table2, null, null, Action.ADMIN); 2838 assertEquals(4, testRegexHandler.runAs(getPrivilegedAction(REGEX_ALL_TABLES)).size()); 2839 2840 // USER_ADMIN, testUserPerms must have a row each. 2841 assertEquals(2, testRegexHandler.runAs(getPrivilegedAction(tableName)).size()); 2842 assertEquals(2, testRegexHandler.runAs(getPrivilegedAction( 2843 NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR + TableName.NAMESPACE_DELIM + tableName) 2844 ).size()); 2845 assertEquals(2, testRegexHandler.runAs(getPrivilegedAction( 2846 ns + TableName.NAMESPACE_DELIM + tableName)).size()); 2847 assertEquals(0, testRegexHandler.runAs(getPrivilegedAction("notMatchingAny")).size()); 2848 2849 deleteTable(TEST_UTIL, table1); 2850 deleteTable(TEST_UTIL, table2); 2851 deleteNamespace(TEST_UTIL, ns); 2852 } 2853 2854 private void verifyAnyCreate(AccessTestAction action) throws Exception { 2855 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_ADMIN_CF, 2856 USER_GROUP_CREATE); 2857 verifyDenied(action, USER_NONE, USER_RO, USER_RW, USER_GROUP_READ, USER_GROUP_WRITE, 2858 USER_GROUP_ADMIN); 2859 } 2860 2861 @Test 2862 public void testPrepareAndCleanBulkLoad() throws Exception { 2863 AccessTestAction prepareBulkLoadAction = new AccessTestAction() { 2864 @Override 2865 public Object run() throws Exception { 2866 ACCESS_CONTROLLER.prePrepareBulkLoad(ObserverContextImpl.createAndPrepare(RCP_ENV)); 2867 return null; 2868 } 2869 }; 2870 AccessTestAction cleanupBulkLoadAction = new AccessTestAction() { 2871 @Override 2872 public Object run() throws Exception { 2873 ACCESS_CONTROLLER.preCleanupBulkLoad(ObserverContextImpl.createAndPrepare(RCP_ENV)); 2874 return null; 2875 } 2876 }; 2877 verifyAnyCreate(prepareBulkLoadAction); 2878 verifyAnyCreate(cleanupBulkLoadAction); 2879 } 2880 2881 @Test 2882 public void testReplicateLogEntries() throws Exception { 2883 AccessTestAction replicateLogEntriesAction = new AccessTestAction() { 2884 @Override 2885 public Object run() throws Exception { 2886 ACCESS_CONTROLLER.preReplicateLogEntries(ObserverContextImpl.createAndPrepare(RSCP_ENV)); 2887 ACCESS_CONTROLLER.postReplicateLogEntries(ObserverContextImpl.createAndPrepare(RSCP_ENV)); 2888 return null; 2889 } 2890 }; 2891 2892 verifyAllowed(replicateLogEntriesAction, SUPERUSER, USER_ADMIN, USER_GROUP_WRITE); 2893 verifyDenied(replicateLogEntriesAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, 2894 USER_GROUP_READ, USER_GROUP_ADMIN, USER_GROUP_CREATE); 2895 } 2896 2897 @Test 2898 public void testAddReplicationPeer() throws Exception { 2899 AccessTestAction action = new AccessTestAction() { 2900 @Override 2901 public Object run() throws Exception { 2902 ACCESS_CONTROLLER.preAddReplicationPeer(ObserverContextImpl.createAndPrepare(CP_ENV), 2903 "test", null); 2904 return null; 2905 } 2906 }; 2907 2908 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2909 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2910 } 2911 2912 @Test 2913 public void testRemoveReplicationPeer() throws Exception { 2914 AccessTestAction action = new AccessTestAction() { 2915 @Override 2916 public Object run() throws Exception { 2917 ACCESS_CONTROLLER.preRemoveReplicationPeer(ObserverContextImpl.createAndPrepare(CP_ENV), 2918 "test"); 2919 return null; 2920 } 2921 }; 2922 2923 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2924 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2925 } 2926 2927 @Test 2928 public void testEnableReplicationPeer() throws Exception { 2929 AccessTestAction action = new AccessTestAction() { 2930 @Override 2931 public Object run() throws Exception { 2932 ACCESS_CONTROLLER.preEnableReplicationPeer(ObserverContextImpl.createAndPrepare(CP_ENV), 2933 "test"); 2934 return null; 2935 } 2936 }; 2937 2938 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2939 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2940 } 2941 2942 @Test 2943 public void testDisableReplicationPeer() throws Exception { 2944 AccessTestAction action = new AccessTestAction() { 2945 @Override 2946 public Object run() throws Exception { 2947 ACCESS_CONTROLLER.preDisableReplicationPeer(ObserverContextImpl.createAndPrepare(CP_ENV), 2948 "test"); 2949 return null; 2950 } 2951 }; 2952 2953 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2954 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2955 } 2956 2957 @Test 2958 public void testGetReplicationPeerConfig() throws Exception { 2959 AccessTestAction action = new AccessTestAction() { 2960 @Override 2961 public Object run() throws Exception { 2962 ACCESS_CONTROLLER.preGetReplicationPeerConfig( 2963 ObserverContextImpl.createAndPrepare(CP_ENV), "test"); 2964 return null; 2965 } 2966 }; 2967 2968 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2969 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2970 } 2971 2972 @Test 2973 public void testUpdateReplicationPeerConfig() throws Exception { 2974 AccessTestAction action = new AccessTestAction() { 2975 @Override 2976 public Object run() throws Exception { 2977 ACCESS_CONTROLLER.preUpdateReplicationPeerConfig( 2978 ObserverContextImpl.createAndPrepare(CP_ENV), "test", new ReplicationPeerConfig()); 2979 return null; 2980 } 2981 }; 2982 2983 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2984 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 2985 } 2986 2987 @Test 2988 public void testListReplicationPeers() throws Exception { 2989 AccessTestAction action = new AccessTestAction() { 2990 @Override 2991 public Object run() throws Exception { 2992 ACCESS_CONTROLLER.preListReplicationPeers(ObserverContextImpl.createAndPrepare(CP_ENV), 2993 "test"); 2994 return null; 2995 } 2996 }; 2997 2998 verifyAllowed(action, SUPERUSER, USER_ADMIN); 2999 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 3000 } 3001 3002 @Test 3003 public void testRemoteLocks() throws Exception { 3004 String namespace = "preQueueNs"; 3005 final TableName tableName = TableName.valueOf(namespace, name.getMethodName()); 3006 HRegionInfo[] regionInfos = new HRegionInfo[] {new HRegionInfo(tableName)}; 3007 3008 // Setup Users 3009 // User will be granted ADMIN and CREATE on namespace. Should be denied before grant. 3010 User namespaceUser = User.createUserForTesting(conf, "qLNSUser", new String[0]); 3011 // User will be granted ADMIN and CREATE on table. Should be denied before grant. 3012 User tableACUser = User.createUserForTesting(conf, "qLTableACUser", new String[0]); 3013 // User will be granted READ, WRITE, EXECUTE on table. Should be denied. 3014 User tableRWXUser = User.createUserForTesting(conf, "qLTableRWXUser", new String[0]); 3015 grantOnTable(TEST_UTIL, tableRWXUser.getShortName(), tableName, null, null, 3016 Action.READ, Action.WRITE, Action.EXEC); 3017 // User with global READ, WRITE, EXECUTE should be denied lock access. 3018 User globalRWXUser = User.createUserForTesting(conf, "qLGlobalRWXUser", new String[0]); 3019 grantGlobal(TEST_UTIL, globalRWXUser.getShortName(), Action.READ, Action.WRITE, Action.EXEC); 3020 3021 AccessTestAction namespaceLockAction = new AccessTestAction() { 3022 @Override public Object run() throws Exception { 3023 ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), namespace, 3024 null, null, null); 3025 return null; 3026 } 3027 }; 3028 verifyAllowed(namespaceLockAction, SUPERUSER, USER_ADMIN); 3029 verifyDenied(namespaceLockAction, globalRWXUser, tableACUser, namespaceUser, tableRWXUser); 3030 grantOnNamespace(TEST_UTIL, namespaceUser.getShortName(), namespace, Action.ADMIN); 3031 // Why I need this pause? I don't need it elsewhere. 3032 Threads.sleep(1000); 3033 verifyAllowed(namespaceLockAction, namespaceUser); 3034 3035 AccessTestAction tableLockAction = new AccessTestAction() { 3036 @Override public Object run() throws Exception { 3037 ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), 3038 null, tableName, null, null); 3039 return null; 3040 } 3041 }; 3042 verifyAllowed(tableLockAction, SUPERUSER, USER_ADMIN, namespaceUser); 3043 verifyDenied(tableLockAction, globalRWXUser, tableACUser, tableRWXUser); 3044 grantOnTable(TEST_UTIL, tableACUser.getShortName(), tableName, null, null, 3045 Action.ADMIN, Action.CREATE); 3046 verifyAllowed(tableLockAction, tableACUser); 3047 3048 AccessTestAction regionsLockAction = new AccessTestAction() { 3049 @Override public Object run() throws Exception { 3050 ACCESS_CONTROLLER.preRequestLock(ObserverContextImpl.createAndPrepare(CP_ENV), 3051 null, null, regionInfos, null); 3052 return null; 3053 } 3054 }; 3055 verifyAllowed(regionsLockAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser); 3056 verifyDenied(regionsLockAction, globalRWXUser, tableRWXUser); 3057 3058 // Test heartbeats 3059 // Create a lock procedure and try sending heartbeat to it. It doesn't matter how the lock 3060 // was created, we just need namespace from the lock's tablename. 3061 LockProcedure proc = new LockProcedure(conf, tableName, LockType.EXCLUSIVE, "test", null); 3062 AccessTestAction regionLockHeartbeatAction = new AccessTestAction() { 3063 @Override public Object run() throws Exception { 3064 ACCESS_CONTROLLER.preLockHeartbeat(ObserverContextImpl.createAndPrepare(CP_ENV), 3065 proc.getTableName(), proc.getDescription()); 3066 return null; 3067 } 3068 }; 3069 verifyAllowed(regionLockHeartbeatAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser); 3070 verifyDenied(regionLockHeartbeatAction, globalRWXUser, tableRWXUser); 3071 } 3072 3073 @Test 3074 public void testAccessControlRevokeOnlyFewPermission() throws Throwable { 3075 TableName tname = TableName.valueOf("revoke"); 3076 try { 3077 TEST_UTIL.createTable(tname, TEST_FAMILY); 3078 User testUserPerms = User.createUserForTesting(conf, "revokePerms", new String[0]); 3079 Permission.Action[] actions = { Action.READ, Action.WRITE }; 3080 AccessControlClient.grant(TEST_UTIL.getConnection(), tname, testUserPerms.getShortName(), 3081 null, null, actions); 3082 3083 List<UserPermission> userPermissions = AccessControlClient 3084 .getUserPermissions(TEST_UTIL.getConnection(), tname.getNameAsString()); 3085 assertEquals(2, userPermissions.size()); 3086 3087 AccessControlClient.revoke(TEST_UTIL.getConnection(), tname, testUserPerms.getShortName(), 3088 null, null, Action.WRITE); 3089 3090 userPermissions = AccessControlClient.getUserPermissions(TEST_UTIL.getConnection(), 3091 tname.getNameAsString()); 3092 assertEquals(2, userPermissions.size()); 3093 3094 Permission.Action[] expectedAction = { Action.READ }; 3095 boolean userFound = false; 3096 for (UserPermission p : userPermissions) { 3097 if (testUserPerms.getShortName().equals(Bytes.toString(p.getUser()))) { 3098 assertArrayEquals(expectedAction, p.getActions()); 3099 userFound = true; 3100 break; 3101 } 3102 } 3103 assertTrue(userFound); 3104 } finally { 3105 TEST_UTIL.deleteTable(tname); 3106 } 3107 } 3108 3109 @Test 3110 public void testGetClusterStatus() throws Exception { 3111 AccessTestAction action = new AccessTestAction() { 3112 @Override 3113 public Object run() throws Exception { 3114 ACCESS_CONTROLLER.preGetClusterMetrics(ObserverContextImpl.createAndPrepare(CP_ENV)); 3115 return null; 3116 } 3117 }; 3118 3119 verifyAllowed( 3120 action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); 3121 } 3122 3123 @Test 3124 public void testExecuteProcedures() throws Exception { 3125 AccessTestAction action = new AccessTestAction() { 3126 @Override 3127 public Object run() throws Exception { 3128 ACCESS_CONTROLLER.preExecuteProcedures(ObserverContextImpl.createAndPrepare(RSCP_ENV)); 3129 return null; 3130 } 3131 }; 3132 3133 verifyAllowed(action, SUPERUSER); 3134 verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER, USER_ADMIN); 3135 } 3136 3137 @Test 3138 public void testTableAdmin() throws Exception { 3139 3140 // Create a user with table admin permissions only 3141 User userTableAdmin = User.createUserForTesting(conf, "table_admin", new String[0]); 3142 grantOnTable(TEST_UTIL, userTableAdmin.getShortName(), TEST_TABLE, null, null, 3143 Permission.Action.ADMIN); 3144 3145 AccessTestAction grantAction = new AccessTestAction() { 3146 @Override 3147 public Object run() throws Exception { 3148 try (Connection conn = ConnectionFactory.createConnection(conf); 3149 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { 3150 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); 3151 AccessControlService.BlockingInterface protocol = 3152 AccessControlService.newBlockingStub(service); 3153 AccessControlUtil.grant(null, protocol, USER_NONE.getShortName(), TEST_TABLE, null, null, 3154 false, Action.READ); 3155 } 3156 return null; 3157 } 3158 }; 3159 3160 AccessTestAction revokeAction = new AccessTestAction() { 3161 @Override 3162 public Object run() throws Exception { 3163 try (Connection conn = ConnectionFactory.createConnection(conf); 3164 Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { 3165 BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); 3166 AccessControlService.BlockingInterface protocol = 3167 AccessControlService.newBlockingStub(service); 3168 AccessControlUtil.revoke(null, protocol, USER_NONE.getShortName(), TEST_TABLE, null, null, 3169 Action.READ); 3170 } 3171 return null; 3172 } 3173 }; 3174 3175 verifyAllowed(userTableAdmin, grantAction); 3176 verifyAllowed(userTableAdmin, revokeAction); 3177 } 3178}