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