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