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