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