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