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