001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security.access; 019 020import static org.apache.hadoop.hbase.AuthUtil.toGroupEntry; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertFalse; 023import static org.junit.jupiter.api.Assertions.assertNotNull; 024import static org.junit.jupiter.api.Assertions.assertTrue; 025 026import java.util.Arrays; 027import java.util.List; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.Coprocessor; 030import org.apache.hadoop.hbase.HBaseTestingUtil; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.NamespaceDescriptor; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.TableNameTestExtension; 035import org.apache.hadoop.hbase.TableNotFoundException; 036import org.apache.hadoop.hbase.client.Admin; 037import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 038import org.apache.hadoop.hbase.client.Connection; 039import org.apache.hadoop.hbase.client.ConnectionFactory; 040import org.apache.hadoop.hbase.client.Put; 041import org.apache.hadoop.hbase.client.Result; 042import org.apache.hadoop.hbase.client.ResultScanner; 043import org.apache.hadoop.hbase.client.Scan; 044import org.apache.hadoop.hbase.client.Table; 045import org.apache.hadoop.hbase.client.TableDescriptor; 046import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 047import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; 048import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment; 049import org.apache.hadoop.hbase.master.MasterCoprocessorHost; 050import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost; 051import org.apache.hadoop.hbase.security.User; 052import org.apache.hadoop.hbase.security.access.Permission.Action; 053import org.apache.hadoop.hbase.testclassification.MediumTests; 054import org.apache.hadoop.hbase.testclassification.SecurityTests; 055import org.apache.hadoop.hbase.util.Bytes; 056import org.apache.hadoop.hbase.zookeeper.ZKUtil; 057import org.apache.hadoop.hbase.zookeeper.ZKWatcher; 058import org.junit.jupiter.api.AfterAll; 059import org.junit.jupiter.api.AfterEach; 060import org.junit.jupiter.api.BeforeAll; 061import org.junit.jupiter.api.BeforeEach; 062import org.junit.jupiter.api.Tag; 063import org.junit.jupiter.api.Test; 064import org.junit.jupiter.api.extension.RegisterExtension; 065import org.slf4j.Logger; 066import org.slf4j.LoggerFactory; 067 068@Tag(SecurityTests.TAG) 069@Tag(MediumTests.TAG) 070public class TestAccessController2 extends SecureTestUtil { 071 072 private static final Logger LOG = LoggerFactory.getLogger(TestAccessController2.class); 073 074 private static final byte[] TEST_ROW = Bytes.toBytes("test"); 075 private static final byte[] TEST_FAMILY = Bytes.toBytes("f"); 076 private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q"); 077 private static final byte[] TEST_VALUE = Bytes.toBytes("value"); 078 079 private static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 080 private static Configuration conf; 081 082 /** 083 * The systemUserConnection created here is tied to the system user. In case, you are planning to 084 * create AccessTestAction, DON'T use this systemUserConnection as the 'doAs' user gets eclipsed 085 * by the system user. 086 */ 087 private static Connection systemUserConnection; 088 089 private final static byte[] Q1 = Bytes.toBytes("q1"); 090 private final static byte[] value1 = Bytes.toBytes("value1"); 091 092 private static byte[] TEST_FAMILY_2 = Bytes.toBytes("f2"); 093 private static byte[] TEST_ROW_2 = Bytes.toBytes("r2"); 094 private final static byte[] Q2 = Bytes.toBytes("q2"); 095 private final static byte[] value2 = Bytes.toBytes("value2"); 096 097 private static byte[] TEST_ROW_3 = Bytes.toBytes("r3"); 098 099 private static final String TESTGROUP_1 = "testgroup_1"; 100 private static final String TESTGROUP_2 = "testgroup_2"; 101 102 private static User TESTGROUP1_USER1; 103 private static User TESTGROUP2_USER1; 104 105 @RegisterExtension 106 public TableNameTestExtension testTable = new TableNameTestExtension(); 107 private String namespace = "testNamespace"; 108 private String tname = namespace + ":testtable1"; 109 private TableName tableName = TableName.valueOf(tname); 110 private static String TESTGROUP_1_NAME; 111 112 @BeforeAll 113 public static void setupBeforeClass() throws Exception { 114 conf = TEST_UTIL.getConfiguration(); 115 // Up the handlers; this test needs more than usual. 116 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); 117 // Enable security 118 enableSecurity(conf); 119 // Verify enableSecurity sets up what we require 120 verifyConfiguration(conf); 121 TEST_UTIL.startMiniCluster(); 122 // Wait for the ACL table to become available 123 TEST_UTIL.waitUntilAllRegionsAssigned(PermissionStorage.ACL_TABLE_NAME); 124 125 TESTGROUP_1_NAME = toGroupEntry(TESTGROUP_1); 126 TESTGROUP1_USER1 = 127 User.createUserForTesting(conf, "testgroup1_user1", new String[] { TESTGROUP_1 }); 128 TESTGROUP2_USER1 = 129 User.createUserForTesting(conf, "testgroup2_user2", new String[] { TESTGROUP_2 }); 130 131 systemUserConnection = ConnectionFactory.createConnection(conf); 132 } 133 134 @BeforeEach 135 public void setUp() throws Exception { 136 createNamespace(TEST_UTIL, NamespaceDescriptor.create(namespace).build()); 137 try (Table table = 138 createTable(TEST_UTIL, tableName, new byte[][] { TEST_FAMILY, TEST_FAMILY_2 })) { 139 TEST_UTIL.waitTableEnabled(tableName); 140 141 // Ingesting test data. 142 table.put(Arrays.asList(new Put(TEST_ROW).addColumn(TEST_FAMILY, Q1, value1), 143 new Put(TEST_ROW_2).addColumn(TEST_FAMILY, Q2, value2), 144 new Put(TEST_ROW_3).addColumn(TEST_FAMILY_2, Q1, value1))); 145 } 146 147 assertEquals(1, PermissionStorage.getTablePermissions(conf, tableName).size()); 148 try { 149 assertEquals(1, 150 AccessControlClient.getUserPermissions(systemUserConnection, tableName.toString()).size()); 151 } catch (Throwable e) { 152 LOG.error("Error during call of AccessControlClient.getUserPermissions. ", e); 153 } 154 155 } 156 157 @AfterAll 158 public static void tearDownAfterClass() throws Exception { 159 systemUserConnection.close(); 160 TEST_UTIL.shutdownMiniCluster(); 161 } 162 163 @AfterEach 164 public void tearDown() throws Exception { 165 // Clean the _acl_ table 166 try { 167 deleteTable(TEST_UTIL, tableName); 168 } catch (TableNotFoundException ex) { 169 // Test deleted the table, no problem 170 LOG.info("Test deleted table " + tableName); 171 } 172 deleteNamespace(TEST_UTIL, namespace); 173 // Verify all table/namespace permissions are erased 174 assertEquals(0, PermissionStorage.getTablePermissions(conf, tableName).size()); 175 assertEquals(0, PermissionStorage.getNamespacePermissions(conf, namespace).size()); 176 } 177 178 @Test 179 public void testCreateWithCorrectOwner() throws Exception { 180 // Create a test user 181 final User testUser = 182 User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser", new String[0]); 183 // Grant the test user the ability to create tables 184 SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE); 185 verifyAllowed(new AccessTestAction() { 186 @Override 187 public Object run() throws Exception { 188 TableDescriptor tableDescriptor = 189 TableDescriptorBuilder.newBuilder(testTable.getTableName()) 190 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build(); 191 try (Connection connection = 192 ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) { 193 try (Admin admin = connection.getAdmin()) { 194 createTable(TEST_UTIL, admin, tableDescriptor); 195 } 196 } 197 return null; 198 } 199 }, testUser); 200 TEST_UTIL.waitTableAvailable(testTable.getTableName()); 201 // Verify that owner permissions have been granted to the test user on the 202 // table just created 203 List<UserPermission> perms = PermissionStorage 204 .getTablePermissions(conf, testTable.getTableName()).get(testUser.getShortName()); 205 assertNotNull(perms); 206 assertFalse(perms.isEmpty()); 207 // Should be RWXCA 208 assertTrue(perms.get(0).getPermission().implies(Permission.Action.READ)); 209 assertTrue(perms.get(0).getPermission().implies(Permission.Action.WRITE)); 210 assertTrue(perms.get(0).getPermission().implies(Permission.Action.EXEC)); 211 assertTrue(perms.get(0).getPermission().implies(Permission.Action.CREATE)); 212 assertTrue(perms.get(0).getPermission().implies(Permission.Action.ADMIN)); 213 } 214 215 @Test 216 public void testCreateTableWithGroupPermissions() throws Exception { 217 grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.CREATE); 218 try { 219 AccessTestAction createAction = new AccessTestAction() { 220 @Override 221 public Object run() throws Exception { 222 TableDescriptor tableDescriptor = 223 TableDescriptorBuilder.newBuilder(testTable.getTableName()) 224 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build(); 225 try (Connection connection = 226 ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) { 227 try (Admin admin = connection.getAdmin()) { 228 admin.createTable(tableDescriptor); 229 } 230 } 231 return null; 232 } 233 }; 234 verifyAllowed(createAction, TESTGROUP1_USER1); 235 verifyDenied(createAction, TESTGROUP2_USER1); 236 } finally { 237 revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.CREATE); 238 } 239 } 240 241 @Test 242 public void testACLTableAccess() throws Exception { 243 final Configuration conf = TEST_UTIL.getConfiguration(); 244 245 // Superuser 246 User superUser = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 247 248 // Global users 249 User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]); 250 User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]); 251 User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]); 252 User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]); 253 SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ); 254 SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE); 255 SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE); 256 SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN); 257 258 // Namespace users 259 User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]); 260 User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]); 261 User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]); 262 User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]); 263 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsRead.getShortName(), 264 testTable.getTableName().getNamespaceAsString(), Action.READ); 265 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsWrite.getShortName(), 266 testTable.getTableName().getNamespaceAsString(), Action.WRITE); 267 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsCreate.getShortName(), 268 testTable.getTableName().getNamespaceAsString(), Action.CREATE); 269 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsAdmin.getShortName(), 270 testTable.getTableName().getNamespaceAsString(), Action.ADMIN); 271 272 // Table users 273 User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]); 274 User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]); 275 User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]); 276 User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]); 277 SecureTestUtil.grantOnTable(TEST_UTIL, tableRead.getShortName(), testTable.getTableName(), null, 278 null, Action.READ); 279 SecureTestUtil.grantOnTable(TEST_UTIL, tableWrite.getShortName(), testTable.getTableName(), 280 null, null, Action.WRITE); 281 SecureTestUtil.grantOnTable(TEST_UTIL, tableCreate.getShortName(), testTable.getTableName(), 282 null, null, Action.CREATE); 283 SecureTestUtil.grantOnTable(TEST_UTIL, tableAdmin.getShortName(), testTable.getTableName(), 284 null, null, Action.ADMIN); 285 286 grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.WRITE); 287 try { 288 // Write tests 289 290 AccessTestAction writeAction = new AccessTestAction() { 291 @Override 292 public Object run() throws Exception { 293 294 try (Connection conn = ConnectionFactory.createConnection(conf); 295 Table t = conn.getTable(PermissionStorage.ACL_TABLE_NAME)) { 296 t.put(new Put(TEST_ROW).addColumn(PermissionStorage.ACL_LIST_FAMILY, TEST_QUALIFIER, 297 TEST_VALUE)); 298 return null; 299 } finally { 300 } 301 } 302 }; 303 304 // All writes to ACL table denied except for GLOBAL WRITE permission and superuser 305 306 verifyDenied(writeAction, globalAdmin, globalCreate, globalRead, TESTGROUP2_USER1); 307 verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite); 308 verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite); 309 verifyAllowed(writeAction, superUser, globalWrite, TESTGROUP1_USER1); 310 } finally { 311 revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.WRITE); 312 } 313 314 grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.READ); 315 try { 316 // Read tests 317 318 AccessTestAction scanAction = new AccessTestAction() { 319 @Override 320 public Object run() throws Exception { 321 try (Connection conn = ConnectionFactory.createConnection(conf); 322 Table t = conn.getTable(PermissionStorage.ACL_TABLE_NAME)) { 323 ResultScanner s = t.getScanner(new Scan()); 324 try { 325 for (Result r = s.next(); r != null; r = s.next()) { 326 // do nothing 327 } 328 } finally { 329 s.close(); 330 } 331 return null; 332 } 333 } 334 }; 335 336 // All reads from ACL table denied except for GLOBAL READ and superuser 337 338 verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite, TESTGROUP2_USER1); 339 verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite); 340 verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite); 341 verifyAllowed(scanAction, superUser, globalRead, TESTGROUP1_USER1); 342 } finally { 343 revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.READ); 344 } 345 } 346 347 /* 348 * Test table scan operation at table, column family and column qualifier level. 349 */ 350 @Test 351 public void testPostGrantAndRevokeScanAction() throws Exception { 352 AccessTestAction scanTableActionForGroupWithTableLevelAccess = new AccessTestAction() { 353 @Override 354 public Void run() throws Exception { 355 try (Connection connection = ConnectionFactory.createConnection(conf); 356 Table table = connection.getTable(tableName)) { 357 Scan s1 = new Scan(); 358 try (ResultScanner scanner1 = table.getScanner(s1)) { 359 Result[] next1 = scanner1.next(5); 360 assertTrue(next1.length == 3, 361 "User having table level access should be able to scan all " 362 + "the data in the table."); 363 } 364 } 365 return null; 366 } 367 }; 368 369 AccessTestAction scanTableActionForGroupWithFamilyLevelAccess = new AccessTestAction() { 370 @Override 371 public Void run() throws Exception { 372 try (Connection connection = ConnectionFactory.createConnection(conf); 373 Table table = connection.getTable(tableName)) { 374 Scan s1 = new Scan(); 375 try (ResultScanner scanner1 = table.getScanner(s1)) { 376 Result[] next1 = scanner1.next(5); 377 assertTrue(next1.length == 2, 378 "User having column family level access should be able to scan all " 379 + "the data belonging to that family."); 380 } 381 } 382 return null; 383 } 384 }; 385 386 AccessTestAction scanFamilyActionForGroupWithFamilyLevelAccess = new AccessTestAction() { 387 @Override 388 public Void run() throws Exception { 389 try (Connection connection = ConnectionFactory.createConnection(conf); 390 Table table = connection.getTable(tableName)) { 391 Scan s1 = new Scan(); 392 s1.addFamily(TEST_FAMILY_2); 393 try (ResultScanner scanner1 = table.getScanner(s1)) { 394 scanner1.next(); 395 } 396 } 397 return null; 398 } 399 }; 400 401 AccessTestAction scanTableActionForGroupWithQualifierLevelAccess = new AccessTestAction() { 402 @Override 403 public Void run() throws Exception { 404 try (Connection connection = ConnectionFactory.createConnection(conf); 405 Table table = connection.getTable(tableName)) { 406 Scan s1 = new Scan(); 407 try (ResultScanner scanner1 = table.getScanner(s1)) { 408 Result[] next1 = scanner1.next(5); 409 assertTrue(next1.length == 1, 410 "User having column qualifier level access should be able to scan " 411 + "that column family qualifier data."); 412 } 413 } 414 return null; 415 } 416 }; 417 418 AccessTestAction scanFamilyActionForGroupWithQualifierLevelAccess = new AccessTestAction() { 419 @Override 420 public Void run() throws Exception { 421 try (Connection connection = ConnectionFactory.createConnection(conf); 422 Table table = connection.getTable(tableName)) { 423 Scan s1 = new Scan(); 424 s1.addFamily(TEST_FAMILY_2); 425 try (ResultScanner scanner1 = table.getScanner(s1)) { 426 scanner1.next(); 427 } 428 } 429 return null; 430 } 431 }; 432 433 AccessTestAction scanQualifierActionForGroupWithQualifierLevelAccess = new AccessTestAction() { 434 @Override 435 public Void run() throws Exception { 436 try (Connection connection = ConnectionFactory.createConnection(conf); 437 Table table = connection.getTable(tableName)) { 438 Scan s1 = new Scan(); 439 s1.addColumn(TEST_FAMILY, Q2); 440 try (ResultScanner scanner1 = table.getScanner(s1)) { 441 scanner1.next(); 442 } 443 } 444 return null; 445 } 446 }; 447 448 // Verify user from a group which has table level access can read all the data and group which 449 // has no access can't read any data. 450 grantOnTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, null, null, Action.READ); 451 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess); 452 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithTableLevelAccess); 453 454 // Verify user from a group whose table level access has been revoked can't read any data. 455 revokeFromTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, null, null); 456 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess); 457 458 // Verify user from a group which has column family level access can read all the data 459 // belonging to that family and group which has no access can't read any data. 460 grantOnTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, TEST_FAMILY, null, Permission.Action.READ); 461 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess); 462 verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithFamilyLevelAccess); 463 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithFamilyLevelAccess); 464 verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithFamilyLevelAccess); 465 466 // Verify user from a group whose column family level access has been revoked can't read any 467 // data from that family. 468 revokeFromTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, TEST_FAMILY, null); 469 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess); 470 471 // Verify user from a group which has column qualifier level access can read data that has this 472 // family and qualifier, and group which has no access can't read any data. 473 grantOnTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, TEST_FAMILY, Q1, Action.READ); 474 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess); 475 verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithQualifierLevelAccess); 476 verifyDenied(TESTGROUP1_USER1, scanQualifierActionForGroupWithQualifierLevelAccess); 477 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithQualifierLevelAccess); 478 verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithQualifierLevelAccess); 479 verifyDenied(TESTGROUP2_USER1, scanQualifierActionForGroupWithQualifierLevelAccess); 480 481 // Verify user from a group whose column qualifier level access has been revoked can't read the 482 // data having this column family and qualifier. 483 revokeFromTable(TEST_UTIL, TESTGROUP_1_NAME, tableName, TEST_FAMILY, Q1); 484 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess); 485 } 486 487 public static class MyAccessController extends AccessController { 488 } 489 490 @Test 491 public void testCoprocessorLoading() throws Exception { 492 MasterCoprocessorHost cpHost = 493 TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost(); 494 cpHost.load(MyAccessController.class, Coprocessor.PRIORITY_HIGHEST, conf); 495 AccessController ACCESS_CONTROLLER = cpHost.findCoprocessor(MyAccessController.class); 496 MasterCoprocessorEnvironment CP_ENV = 497 cpHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); 498 RegionServerCoprocessorHost rsHost = 499 TEST_UTIL.getMiniHBaseCluster().getRegionServer(0).getRegionServerCoprocessorHost(); 500 RegionServerCoprocessorEnvironment RSCP_ENV = 501 rsHost.createEnvironment(ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); 502 } 503 504 @Test 505 public void testACLZNodeDeletion() throws Exception { 506 String baseAclZNode = "/hbase/acl/"; 507 String ns = "testACLZNodeDeletionNamespace"; 508 NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build(); 509 createNamespace(TEST_UTIL, desc); 510 511 final TableName table = TableName.valueOf(ns, "testACLZNodeDeletionTable"); 512 final byte[] family = Bytes.toBytes("f1"); 513 TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(table) 514 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)).build(); 515 createTable(TEST_UTIL, tableDescriptor); 516 517 // Namespace needs this, as they follow the lazy creation of ACL znode. 518 grantOnNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN); 519 ZKWatcher zkw = TEST_UTIL.getMiniHBaseCluster().getMaster().getZooKeeper(); 520 assertTrue(ZKUtil.checkExists(zkw, baseAclZNode + table.getNameAsString()) != -1, 521 "The acl znode for table should exist"); 522 assertTrue(ZKUtil.checkExists(zkw, baseAclZNode + convertToNamespace(ns)) != -1, 523 "The acl znode for namespace should exist"); 524 525 revokeFromNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN); 526 deleteTable(TEST_UTIL, table); 527 deleteNamespace(TEST_UTIL, ns); 528 529 assertTrue(ZKUtil.checkExists(zkw, baseAclZNode + table.getNameAsString()) == -1, 530 "The acl znode for table should have been deleted"); 531 assertTrue(ZKUtil.checkExists(zkw, baseAclZNode + convertToNamespace(ns)) == -1, 532 "The acl znode for namespace should have been deleted"); 533 } 534}