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.security.access.Permission.Action.READ; 021import static org.apache.hadoop.hbase.security.access.Permission.Action.WRITE; 022import static org.apache.hadoop.hbase.security.access.SnapshotScannerHDFSAclController.SnapshotScannerHDFSAclStorage.hasUserGlobalHdfsAcl; 023import static org.apache.hadoop.hbase.security.access.SnapshotScannerHDFSAclController.SnapshotScannerHDFSAclStorage.hasUserNamespaceHdfsAcl; 024import static org.apache.hadoop.hbase.security.access.SnapshotScannerHDFSAclController.SnapshotScannerHDFSAclStorage.hasUserTableHdfsAcl; 025import static org.junit.jupiter.api.Assertions.assertEquals; 026import static org.junit.jupiter.api.Assertions.assertFalse; 027import static org.junit.jupiter.api.Assertions.assertTrue; 028 029import java.io.IOException; 030import java.util.List; 031import org.apache.hadoop.conf.Configuration; 032import org.apache.hadoop.fs.FileSystem; 033import org.apache.hadoop.fs.Path; 034import org.apache.hadoop.fs.permission.AclEntry; 035import org.apache.hadoop.fs.permission.AclEntryScope; 036import org.apache.hadoop.fs.permission.FsPermission; 037import org.apache.hadoop.hbase.HBaseTestingUtil; 038import org.apache.hadoop.hbase.NamespaceDescriptor; 039import org.apache.hadoop.hbase.TableName; 040import org.apache.hadoop.hbase.client.Admin; 041import org.apache.hadoop.hbase.client.Table; 042import org.apache.hadoop.hbase.client.TableDescriptor; 043import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 044import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 045import org.apache.hadoop.hbase.master.cleaner.HFileCleaner; 046import org.apache.hadoop.hbase.security.User; 047import org.apache.hadoop.hbase.testclassification.LargeTests; 048import org.apache.hadoop.hbase.testclassification.SecurityTests; 049import org.apache.hadoop.hbase.util.FSUtils; 050import org.apache.hadoop.hbase.util.HFileArchiveUtil; 051import org.apache.hadoop.hbase.util.Threads; 052import org.junit.jupiter.api.AfterAll; 053import org.junit.jupiter.api.BeforeAll; 054import org.junit.jupiter.api.Tag; 055import org.junit.jupiter.api.Test; 056import org.junit.jupiter.api.TestInfo; 057import org.slf4j.Logger; 058import org.slf4j.LoggerFactory; 059 060@Tag(SecurityTests.TAG) 061@Tag(LargeTests.TAG) 062public class TestSnapshotScannerHDFSAclController { 063 private static final Logger LOG = 064 LoggerFactory.getLogger(TestSnapshotScannerHDFSAclController.class); 065 066 private static final String UN_GRANT_USER = "un_grant_user"; 067 private static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 068 private static Configuration conf = TEST_UTIL.getConfiguration(); 069 private static Admin admin = null; 070 private static FileSystem FS = null; 071 private static Path rootDir = null; 072 private static User unGrantUser = null; 073 private static SnapshotScannerHDFSAclHelper helper; 074 private static Table aclTable; 075 076 @BeforeAll 077 public static void setupBeforeClass() throws Exception { 078 // enable hdfs acl and set umask to 027 079 conf.setBoolean("dfs.namenode.acls.enabled", true); 080 conf.set("fs.permissions.umask-mode", "027"); 081 // enable hbase hdfs acl feature 082 conf.setBoolean(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, true); 083 // enable secure 084 conf.set(User.HBASE_SECURITY_CONF_KEY, "simple"); 085 conf.set(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_TMP_DIR, 086 SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_TMP_DIR_DEFAULT); 087 SecureTestUtil.enableSecurity(conf); 088 // add SnapshotScannerHDFSAclController coprocessor 089 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, 090 conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY) + "," 091 + SnapshotScannerHDFSAclController.class.getName()); 092 093 TEST_UTIL.startMiniCluster(); 094 SnapshotScannerHDFSAclController coprocessor = TEST_UTIL.getHBaseCluster().getMaster() 095 .getMasterCoprocessorHost().findCoprocessor(SnapshotScannerHDFSAclController.class); 096 TEST_UTIL.waitFor(30000, () -> coprocessor.checkInitialized("check initialized")); 097 TEST_UTIL.waitTableAvailable(PermissionStorage.ACL_TABLE_NAME); 098 099 admin = TEST_UTIL.getAdmin(); 100 rootDir = TEST_UTIL.getDefaultRootDirPath(); 101 FS = rootDir.getFileSystem(conf); 102 unGrantUser = User.createUserForTesting(conf, UN_GRANT_USER, new String[] {}); 103 helper = new SnapshotScannerHDFSAclHelper(conf, admin.getConnection()); 104 105 // set hbase directory permission 106 FsPermission commonDirectoryPermission = 107 new FsPermission(conf.get(SnapshotScannerHDFSAclHelper.COMMON_DIRECTORY_PERMISSION, 108 SnapshotScannerHDFSAclHelper.COMMON_DIRECTORY_PERMISSION_DEFAULT)); 109 Path path = rootDir; 110 while (path != null) { 111 FS.setPermission(path, commonDirectoryPermission); 112 path = path.getParent(); 113 } 114 // set restore directory permission 115 Path restoreDir = new Path(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_TMP_DIR_DEFAULT); 116 if (!FS.exists(restoreDir)) { 117 FS.mkdirs(restoreDir); 118 FS.setPermission(restoreDir, 119 new FsPermission( 120 conf.get(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_DIRECTORY_PERMISSION, 121 SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_DIRECTORY_PERMISSION_DEFAULT))); 122 } 123 path = restoreDir.getParent(); 124 while (path != null) { 125 FS.setPermission(path, commonDirectoryPermission); 126 path = path.getParent(); 127 } 128 aclTable = admin.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME); 129 } 130 131 @AfterAll 132 public static void tearDownAfterClass() throws Exception { 133 TEST_UTIL.shutdownMiniCluster(); 134 } 135 136 private void snapshotAndWait(final String snapShotName, final TableName tableName) 137 throws Exception { 138 admin.snapshot(snapShotName, tableName); 139 LOG.info("Sleep for three seconds, waiting for HDFS Acl setup"); 140 Threads.sleep(3000); 141 } 142 143 @Test 144 public void testGrantGlobal1(TestInfo testInfo) throws Exception { 145 final String grantUserName = testInfo.getTestMethod().get().getName(); 146 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 147 String namespace = testInfo.getTestMethod().get().getName(); 148 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 149 String snapshot1 = namespace + "s1"; 150 String snapshot2 = namespace + "s2"; 151 152 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 153 snapshotAndWait(snapshot1, table); 154 // grant G(R) 155 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 156 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 157 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 158 // grant G(W) with merging existing permissions 159 admin.grant( 160 new UserPermission(grantUserName, Permission.newBuilder().withActions(WRITE).build()), true); 161 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 162 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 163 // grant G(W) without merging 164 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, WRITE); 165 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 166 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 167 // grant G(R) 168 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 169 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 170 // take a snapshot and ACLs are inherited automatically 171 snapshotAndWait(snapshot2, table); 172 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 6); 173 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 174 deleteTable(table); 175 } 176 177 @Test 178 public void testGrantGlobal2(TestInfo testInfo) throws Exception { 179 final String grantUserName = testInfo.getTestMethod().get().getName(); 180 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 181 String namespace1 = testInfo.getTestMethod().get().getName(); 182 TableName table1 = 183 TableName.valueOf(namespace1, testInfo.getTestMethod().get().getName() + ".1"); 184 String namespace2 = namespace1 + "2"; 185 TableName table2 = 186 TableName.valueOf(namespace2, testInfo.getTestMethod().get().getName() + ".2"); 187 String snapshot1 = namespace1 + "s1"; 188 String snapshot2 = namespace2 + "s2"; 189 190 // grant G(R), grant namespace1(R) 191 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 192 // create table in namespace1 and snapshot 193 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 194 snapshotAndWait(snapshot1, table1); 195 admin.grant(new UserPermission(grantUserName, 196 Permission.newBuilder(namespace1).withActions(READ).build()), false); 197 // grant G(W) 198 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, WRITE); 199 // create table in namespace2 and snapshot 200 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 201 snapshotAndWait(snapshot2, table2); 202 // check scan snapshot 203 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 204 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, -1); 205 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 206 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace1)); 207 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace2)); 208 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 209 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace1), grantUserName, true, true); 210 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace2), grantUserName, false, false); 211 deleteTable(table1); 212 deleteTable(table2); 213 } 214 215 @Test 216 public void testGrantGlobal3(TestInfo testInfo) throws Exception { 217 final String grantUserName = testInfo.getTestMethod().get().getName(); 218 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 219 String namespace = testInfo.getTestMethod().get().getName(); 220 TableName table1 = 221 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".1"); 222 TableName table2 = 223 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".2"); 224 String snapshot1 = namespace + "s1"; 225 String snapshot2 = namespace + "s2"; 226 // grant G(R) 227 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 228 // grant table1(R) 229 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 230 snapshotAndWait(snapshot1, table1); 231 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 232 // grant G(W) 233 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, WRITE); 234 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 235 snapshotAndWait(snapshot2, table2); 236 // check scan snapshot 237 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 238 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, -1); 239 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 240 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 241 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 242 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table2)); 243 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 244 checkUserAclEntry(FS, helper.getTableRootPaths(table2, false), grantUserName, false, false); 245 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 246 deleteTable(table1); 247 deleteTable(table2); 248 } 249 250 @Test 251 public void testGrantNamespace1(TestInfo testInfo) throws Exception { 252 final String grantUserName = testInfo.getTestMethod().get().getName(); 253 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 254 String namespace = testInfo.getTestMethod().get().getName(); 255 TableName table1 = 256 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".1"); 257 TableName table2 = 258 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".2"); 259 String snapshot1 = namespace + "s1"; 260 String snapshot2 = namespace + "s2"; 261 262 // create table1 and snapshot 263 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 264 snapshotAndWait(snapshot1, table1); 265 // grant N(R) 266 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 267 // create table2 and snapshot, ACLs can be inherited automatically 268 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 269 snapshotAndWait(snapshot2, table2); 270 // check scan snapshot 271 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 272 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 6); 273 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, unGrantUser, snapshot1, -1); 274 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 275 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 276 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 277 // grant N(W) 278 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 279 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 280 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 281 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, false, false); 282 deleteTable(table1); 283 deleteTable(table2); 284 } 285 286 @Test 287 public void testGrantNamespace2(TestInfo testInfo) throws Exception { 288 final String grantUserName = testInfo.getTestMethod().get().getName(); 289 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 290 String namespace = testInfo.getTestMethod().get().getName(); 291 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 292 String snapshot1 = namespace + "s1"; 293 294 // create table1 and snapshot 295 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 296 snapshotAndWait(snapshot1, table1); 297 298 // grant N(R) 299 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 300 // grant table1(R) 301 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 302 // grant N(W) 303 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 304 // check scan snapshot 305 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 306 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 307 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 308 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 309 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 310 deleteTable(table1); 311 } 312 313 @Test 314 public void testGrantNamespace3(TestInfo testInfo) throws Exception { 315 final String grantUserName = testInfo.getTestMethod().get().getName(); 316 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 317 String namespace = testInfo.getTestMethod().get().getName(); 318 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 319 String snapshot = namespace + "t1"; 320 321 // create table1 and snapshot 322 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 323 snapshotAndWait(snapshot, table); 324 // grant namespace(R) 325 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 326 // grant global(R) 327 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 328 // grant namespace(W) 329 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 330 // check scan snapshot 331 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 332 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 333 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 334 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 335 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, true, true); 336 deleteTable(table); 337 } 338 339 @Test 340 public void testGrantTable(TestInfo testInfo) throws Exception { 341 final String grantUserName = testInfo.getTestMethod().get().getName(); 342 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 343 344 String namespace = testInfo.getTestMethod().get().getName(); 345 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 346 String snapshot1 = namespace + "s1"; 347 String snapshot2 = namespace + "s2"; 348 349 LOG.info("Create table"); 350 try (Table t = TestHDFSAclHelper.createTable(TEST_UTIL, table1)) { 351 TestHDFSAclHelper.put(t); 352 snapshotAndWait(snapshot1, table1); 353 // table owner can scan table snapshot 354 LOG.info("Scan snapshot"); 355 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, 356 User.createUserForTesting(conf, "owner", new String[] {}), snapshot1, 6); 357 // grant table1 family(R) 358 SecureTestUtil.grantOnTable(TEST_UTIL, grantUserName, table1, TestHDFSAclHelper.COLUMN1, null, 359 READ); 360 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 361 362 // grant table1(R) 363 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 364 TestHDFSAclHelper.put2(t); 365 snapshotAndWait(snapshot2, table1); 366 367 // check scan snapshot 368 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 369 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 10); 370 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 371 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 372 } 373 374 // grant table1(W) with merging existing permissions 375 admin.grant( 376 new UserPermission(grantUserName, Permission.newBuilder(table1).withActions(WRITE).build()), 377 true); 378 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 379 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 380 381 // grant table1(W) without merging existing permissions 382 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, WRITE); 383 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 384 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 385 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, false, false); 386 deleteTable(table1); 387 } 388 389 @Test 390 public void testGrantMobTable(TestInfo testInfo) throws Exception { 391 final String grantUserName = testInfo.getTestMethod().get().getName(); 392 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 393 String namespace = testInfo.getTestMethod().get().getName(); 394 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 395 String snapshot = namespace + "s1"; 396 397 try (Table t = TestHDFSAclHelper.createMobTable(TEST_UTIL, table)) { 398 TestHDFSAclHelper.put(t); 399 snapshotAndWait(snapshot, table); 400 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 401 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 402 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 403 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 404 } 405 deleteTable(table); 406 } 407 408 @Test 409 public void testRevokeGlobal1(TestInfo testInfo) throws Exception { 410 final String grantUserName = testInfo.getTestMethod().get().getName(); 411 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 412 String namespace = testInfo.getTestMethod().get().getName(); 413 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 414 String snapshot1 = namespace + "t1"; 415 416 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 417 snapshotAndWait(snapshot1, table1); 418 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 419 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 420 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 421 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 422 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 423 deleteTable(table1); 424 } 425 426 @Test 427 public void testRevokeGlobal2(TestInfo testInfo) throws Exception { 428 final String grantUserName = testInfo.getTestMethod().get().getName(); 429 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 430 431 String namespace = testInfo.getTestMethod().get().getName(); 432 String snapshot1 = namespace + "s1"; 433 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 434 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 435 snapshotAndWait(snapshot1, table1); 436 437 // grant G(R), grant N(R), grant T(R) -> revoke G(R) 438 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 439 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 440 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 441 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 442 // check scan snapshot 443 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 444 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 445 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 446 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 447 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 448 deleteTable(table1); 449 } 450 451 @Test 452 public void testRevokeGlobal3(TestInfo testInfo) throws Exception { 453 final String grantUserName = testInfo.getTestMethod().get().getName(); 454 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 455 456 String namespace = testInfo.getTestMethod().get().getName(); 457 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 458 String snapshot1 = namespace + "t1"; 459 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 460 snapshotAndWait(snapshot1, table1); 461 462 // grant G(R), grant T(R) -> revoke G(R) 463 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 464 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 465 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 466 // check scan snapshot 467 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 468 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 469 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 470 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 471 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 472 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 473 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 474 deleteTable(table1); 475 } 476 477 @Test 478 public void testRevokeNamespace1(TestInfo testInfo) throws Exception { 479 String grantUserName = testInfo.getTestMethod().get().getName(); 480 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 481 String namespace = testInfo.getTestMethod().get().getName(); 482 TableName table1 = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 483 String snapshot1 = namespace + "s1"; 484 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 485 snapshotAndWait(snapshot1, table1); 486 487 // revoke N(R) 488 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 489 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(namespace).build())); 490 // check scan snapshot 491 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 492 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 493 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, false, false); 494 495 // grant N(R), grant G(R) -> revoke N(R) 496 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 497 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 498 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(namespace).build())); 499 // check scan snapshot 500 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 501 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 502 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 503 deleteTable(table1); 504 } 505 506 @Test 507 public void testRevokeNamespace2(TestInfo testInfo) throws Exception { 508 String grantUserName = testInfo.getTestMethod().get().getName(); 509 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 510 String namespace = testInfo.getTestMethod().get().getName(); 511 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 512 String snapshot = namespace + "s1"; 513 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 514 snapshotAndWait(snapshot, table); 515 516 // grant N(R), grant T(R) -> revoke N(R) 517 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 518 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 519 SecureTestUtil.revokeFromNamespace(TEST_UTIL, grantUserName, namespace, READ); 520 // check scan snapshot 521 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 522 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 523 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 524 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 525 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 526 deleteTable(table); 527 } 528 529 @Test 530 public void testRevokeTable1(TestInfo testInfo) throws Exception { 531 final String grantUserName = testInfo.getTestMethod().get().getName(); 532 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 533 String namespace = testInfo.getTestMethod().get().getName(); 534 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 535 String snapshot = namespace + "t1"; 536 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 537 snapshotAndWait(snapshot, table); 538 539 // grant T(R) -> revoke table family 540 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 541 SecureTestUtil.revokeFromTable(TEST_UTIL, grantUserName, table, TestHDFSAclHelper.COLUMN1, null, 542 READ); 543 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 544 545 // grant T(R) -> revoke T(R) 546 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 547 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 548 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, -1); 549 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 550 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, false, false); 551 deleteTable(table); 552 } 553 554 @Test 555 public void testRevokeTable2(TestInfo testInfo) throws Exception { 556 final String grantUserName = testInfo.getTestMethod().get().getName(); 557 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 558 String namespace = testInfo.getTestMethod().get().getName(); 559 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 560 String snapshot = namespace + "t1"; 561 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 562 snapshotAndWait(snapshot, table); 563 564 // grant T(R), grant N(R) -> revoke T(R) 565 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 566 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 567 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 568 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 569 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 570 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 571 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 572 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 573 deleteTable(table); 574 } 575 576 @Test 577 public void testRevokeTable3(TestInfo testInfo) throws Exception { 578 final String grantUserName = testInfo.getTestMethod().get().getName(); 579 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 580 String namespace = testInfo.getTestMethod().get().getName(); 581 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 582 String snapshot = namespace + "t1"; 583 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 584 snapshotAndWait(snapshot, table); 585 586 // grant T(R), grant G(R) -> revoke T(R) 587 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 588 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 589 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 590 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 591 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 592 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 593 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 594 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, true, true); 595 deleteTable(table); 596 } 597 598 @Test 599 public void testTruncateTable(TestInfo testInfo) throws Exception { 600 String grantUserName = testInfo.getTestMethod().get().getName(); 601 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 602 String grantUserName2 = grantUserName + "2"; 603 User grantUser2 = User.createUserForTesting(conf, grantUserName2, new String[] {}); 604 605 String namespace = testInfo.getTestMethod().get().getName(); 606 TableName tableName = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 607 String snapshot = namespace + "s1"; 608 String snapshot2 = namespace + "s2"; 609 try (Table t = TestHDFSAclHelper.createTable(TEST_UTIL, tableName)) { 610 TestHDFSAclHelper.put(t); 611 // snapshot 612 snapshotAndWait(snapshot, tableName); 613 // grant user2 namespace permission 614 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName2, namespace, READ); 615 // grant user table permission 616 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, tableName, READ); 617 // truncate table 618 admin.disableTable(tableName); 619 admin.truncateTable(tableName, true); 620 TestHDFSAclHelper.put2(t); 621 // snapshot 622 snapshotAndWait(snapshot2, tableName); 623 // check scan snapshot 624 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 625 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot, 6); 626 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 9); 627 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot2, 9); 628 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName2, namespace)); 629 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName2, true, true); 630 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, tableName)); 631 checkUserAclEntry(FS, helper.getTableRootPaths(tableName, false), grantUserName, true, true); 632 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 633 } 634 deleteTable(tableName); 635 } 636 637 @Test 638 public void testDeleteTable(TestInfo testInfo) throws Exception { 639 String namespace = testInfo.getTestMethod().get().getName(); 640 String grantUserName1 = namespace + "1"; 641 String grantUserName2 = namespace + "2"; 642 User grantUser1 = User.createUserForTesting(conf, grantUserName1, new String[] {}); 643 User grantUser2 = User.createUserForTesting(conf, grantUserName2, new String[] {}); 644 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 645 String snapshot1 = namespace + "t1"; 646 647 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 648 // snapshot 649 snapshotAndWait(snapshot1, table); 650 // grant user table permission 651 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName1, table, READ); 652 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName2, namespace, READ); 653 // delete table 654 admin.disableTable(table); 655 admin.deleteTable(table); 656 // grantUser2 should have data/ns acl 657 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser1, snapshot1, -1); 658 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot1, 6); 659 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName2, namespace)); 660 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName2, true, true); 661 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName1, table)); 662 checkUserAclEntry(FS, helper.getPathHelper().getDataTableDir(table), grantUserName1, false, 663 false); 664 checkUserAclEntry(FS, helper.getPathHelper().getMobTableDir(table), grantUserName1, false, 665 false); 666 checkUserAclEntry(FS, helper.getPathHelper().getArchiveTableDir(table), grantUserName1, true, 667 false); 668 669 // check tmp table directory does not exist 670 Path tmpTableDir = helper.getPathHelper().getTmpTableDir(table); 671 assertFalse(FS.exists(tmpTableDir)); 672 deleteTable(table); 673 } 674 675 @Test 676 public void testDeleteTable2(TestInfo testInfo) throws Exception { 677 String namespace1 = testInfo.getTestMethod().get().getName() + "1"; 678 String namespace2 = testInfo.getTestMethod().get().getName() + "2"; 679 String grantUser = testInfo.getTestMethod().get().getName(); 680 TableName table = TableName.valueOf(namespace1, testInfo.getTestMethod().get().getName()); 681 682 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 683 // grant user table permission 684 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUser, table, READ); 685 // grant user other namespace permission 686 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUser, namespace2, READ); 687 // delete table 688 admin.disableTable(table); 689 admin.deleteTable(table); 690 // grantUser should have namespace2's acl 691 assertFalse(hasUserTableHdfsAcl(aclTable, grantUser, table)); 692 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUser, namespace2)); 693 } 694 695 @Test 696 public void testDeleteNamespace(TestInfo testInfo) throws Exception { 697 String grantUserName = testInfo.getTestMethod().get().getName(); 698 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 699 String namespace = testInfo.getTestMethod().get().getName(); 700 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 701 String snapshot = namespace + "t1"; 702 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 703 // snapshot 704 snapshotAndWait(snapshot, table); 705 // grant namespace permission 706 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 707 // delete table 708 admin.disableTable(table); 709 admin.deleteTable(table); 710 // delete namespace 711 admin.deleteNamespace(namespace); 712 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 713 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 714 checkUserAclEntry(FS, helper.getPathHelper().getArchiveNsDir(namespace), grantUserName, true, 715 false); 716 717 // check tmp namespace dir does not exist 718 assertFalse(FS.exists(helper.getPathHelper().getTmpNsDir(namespace))); 719 assertFalse(FS.exists(helper.getPathHelper().getDataNsDir(namespace))); 720 // assertFalse(fs.exists(FS, helper.getPathHelper().getMobDataNsDir(namespace))); 721 deleteTable(table); 722 } 723 724 @Test 725 public void testCleanArchiveTableDir(TestInfo testInfo) throws Exception { 726 final String grantUserName = testInfo.getTestMethod().get().getName(); 727 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 728 String namespace = testInfo.getTestMethod().get().getName(); 729 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 730 String snapshot = namespace + "t1"; 731 732 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 733 snapshotAndWait(snapshot, table); 734 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 735 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 736 737 // HFileCleaner will not delete archive table directory even if it's a empty directory 738 HFileCleaner cleaner = TEST_UTIL.getHBaseCluster().getMaster().getHFileCleaner(); 739 cleaner.choreForTesting(); 740 Path archiveTableDir = HFileArchiveUtil.getTableArchivePath(rootDir, table); 741 assertTrue(FS.exists(archiveTableDir)); 742 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 743 744 // Check SnapshotScannerHDFSAclCleaner method 745 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveTableDir(archiveTableDir)); 746 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveNamespaceDir(archiveTableDir.getParent())); 747 assertTrue( 748 SnapshotScannerHDFSAclCleaner.isArchiveDataDir(archiveTableDir.getParent().getParent())); 749 assertFalse(SnapshotScannerHDFSAclCleaner 750 .isArchiveDataDir(archiveTableDir.getParent().getParent().getParent())); 751 deleteTable(table); 752 } 753 754 @Test 755 public void testModifyTable1(TestInfo testInfo) throws Exception { 756 String namespace = testInfo.getTestMethod().get().getName(); 757 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName()); 758 String snapshot = namespace + "t1"; 759 760 String tableUserName = testInfo.getTestMethod().get().getName(); 761 User tableUser = User.createUserForTesting(conf, tableUserName, new String[] {}); 762 String tableUserName2 = tableUserName + "2"; 763 User tableUser2 = User.createUserForTesting(conf, tableUserName2, new String[] {}); 764 String tableUserName3 = tableUserName + "3"; 765 User tableUser3 = User.createUserForTesting(conf, tableUserName3, new String[] {}); 766 String nsUserName = tableUserName + "-ns"; 767 User nsUser = User.createUserForTesting(conf, nsUserName, new String[] {}); 768 String globalUserName = tableUserName + "-global"; 769 User globalUser = User.createUserForTesting(conf, globalUserName, new String[] {}); 770 String globalUserName2 = tableUserName + "-global-2"; 771 User globalUser2 = User.createUserForTesting(conf, globalUserName2, new String[] {}); 772 773 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName, READ); 774 TestHDFSAclHelper.createNamespace(TEST_UTIL, namespace); 775 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsUserName, namespace, READ); 776 TableDescriptor td = TestHDFSAclHelper.createUserScanSnapshotDisabledTable(TEST_UTIL, table); 777 snapshotAndWait(snapshot, table); 778 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName2, READ); 779 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName, table, READ); 780 SecureTestUtil.grantOnTable(TEST_UTIL, tableUserName2, table, TestHDFSAclHelper.COLUMN1, null, 781 READ); 782 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table, WRITE); 783 784 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, -1); 785 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 786 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 787 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, -1); 788 // Global permission is set before table is created, the acl is inherited 789 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 790 // Global permission is set after table is created, the table dir acl is skip 791 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser2, snapshot, -1); 792 793 // enable user scan snapshot 794 admin.modifyTable(TableDescriptorBuilder.newBuilder(td) 795 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "true").build()); 796 // check scan snapshot 797 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, 6); 798 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 799 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 800 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, 6); 801 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 802 // check acl table storage and ACLs in dirs 803 assertTrue(hasUserGlobalHdfsAcl(aclTable, globalUserName)); 804 checkUserAclEntry(FS, helper.getGlobalRootPaths(), globalUserName, true, true); 805 assertTrue(hasUserNamespaceHdfsAcl(aclTable, nsUserName, namespace)); 806 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), nsUserName, true, true); 807 assertTrue(hasUserTableHdfsAcl(aclTable, tableUserName, table)); 808 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), tableUserName, true, true); 809 for (String user : new String[] { tableUserName2, tableUserName3 }) { 810 assertFalse(hasUserTableHdfsAcl(aclTable, user, table)); 811 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), user, false, false); 812 } 813 deleteTable(table); 814 } 815 816 @Test 817 public void testModifyTable2(TestInfo testInfo) throws Exception { 818 String namespace = testInfo.getTestMethod().get().getName(); 819 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".1"); 820 String snapshot = namespace + "t1"; 821 TableName table2 = 822 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".2"); 823 824 String tableUserName = testInfo.getTestMethod().get().getName(); 825 User tableUser = User.createUserForTesting(conf, tableUserName, new String[] {}); 826 String tableUserName2 = tableUserName + "2"; 827 User tableUser2 = User.createUserForTesting(conf, tableUserName2, new String[] {}); 828 String tableUserName3 = tableUserName + "3"; 829 User tableUser3 = User.createUserForTesting(conf, tableUserName3, new String[] {}); 830 String nsUserName = tableUserName + "-ns"; 831 User nsUser = User.createUserForTesting(conf, nsUserName, new String[] {}); 832 String globalUserName = tableUserName + "-global"; 833 User globalUser = User.createUserForTesting(conf, globalUserName, new String[] {}); 834 String globalUserName2 = tableUserName + "-global-2"; 835 User globalUser2 = User.createUserForTesting(conf, globalUserName2, new String[] {}); 836 837 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 838 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName, READ); 839 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName2, READ); 840 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsUserName, namespace, READ); 841 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName, table, READ); 842 SecureTestUtil.grantOnTable(TEST_UTIL, tableUserName2, table, TestHDFSAclHelper.COLUMN1, null, 843 READ); 844 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table, WRITE); 845 846 SecureTestUtil.grantOnNamespace(TEST_UTIL, tableUserName2, namespace, READ); 847 TestHDFSAclHelper.createTable(TEST_UTIL, table2); 848 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table2, READ); 849 // disable user scan snapshot 850 admin.modifyTable(TableDescriptorBuilder.newBuilder(admin.getDescriptor(table)) 851 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "false").build()); 852 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, -1); 853 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 854 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 855 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, -1); 856 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, -1); 857 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser2, snapshot, -1); 858 // check access 859 String[] users = new String[] { globalUserName, globalUserName2, nsUserName, tableUserName, 860 tableUserName2, tableUserName3 }; 861 for (Path path : helper.getTableRootPaths(table, false)) { 862 for (String user : users) { 863 checkUserAclEntry(FS, path, user, false, false); 864 } 865 } 866 String[] nsUsers = new String[] { globalUserName, globalUserName2, nsUserName }; 867 for (Path path : helper.getNamespaceRootPaths(namespace)) { 868 checkUserAclEntry(FS, path, tableUserName, false, false); 869 checkUserAclEntry(FS, path, tableUserName2, true, true); 870 checkUserAclEntry(FS, path, tableUserName3, true, false); 871 for (String user : nsUsers) { 872 checkUserAclEntry(FS, path, user, true, true); 873 } 874 } 875 assertTrue(hasUserNamespaceHdfsAcl(aclTable, nsUserName, namespace)); 876 assertTrue(hasUserNamespaceHdfsAcl(aclTable, tableUserName2, namespace)); 877 assertFalse(hasUserTableHdfsAcl(aclTable, tableUserName, table)); 878 deleteTable(table); 879 deleteTable(table2); 880 } 881 882 @Test 883 public void testRestartMaster(TestInfo testInfo) throws Exception { 884 final String grantUserName = testInfo.getTestMethod().get().getName(); 885 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 886 String namespace = testInfo.getTestMethod().get().getName(); 887 TableName table = TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".1"); 888 TableName table2 = 889 TableName.valueOf(namespace, testInfo.getTestMethod().get().getName() + ".2"); 890 String snapshot = namespace + "t1"; 891 admin.createNamespace(NamespaceDescriptor.create(namespace).build()); 892 893 // create table2 894 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 895 // make some region files in tmp dir and check if master archive these region correctly 896 Path tmpTableDir = helper.getPathHelper().getTmpTableDir(table2); 897 // make a empty region dir, this is an error region 898 FS.mkdirs(new Path(tmpTableDir, "1")); 899 // copy regions from data dir, this is a valid region 900 for (Path regionDir : FSUtils.getRegionDirs(FS, 901 helper.getPathHelper().getDataTableDir(table2))) { 902 FSUtils.copyFilesParallel(FS, regionDir, FS, 903 new Path(tmpTableDir, regionDir.getName() + "abc"), conf, 1); 904 } 905 assertEquals(4, FS.listStatus(tmpTableDir).length); 906 907 // grant N(R) 908 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 909 // restart cluster and tmp directory will not be deleted 910 TEST_UTIL.getMiniHBaseCluster().shutdown(); 911 TEST_UTIL.restartHBaseCluster(1); 912 TEST_UTIL.waitUntilNoRegionsInTransition(); 913 914 // reset the cached configs after restart 915 conf = TEST_UTIL.getConfiguration(); 916 admin = TEST_UTIL.getAdmin(); 917 helper = new SnapshotScannerHDFSAclHelper(conf, admin.getConnection()); 918 919 Path tmpNsDir = helper.getPathHelper().getTmpNsDir(namespace); 920 assertTrue(FS.exists(tmpNsDir)); 921 // check all regions in tmp table2 dir are archived 922 assertEquals(0, FS.listStatus(tmpTableDir).length); 923 924 // create table1 and snapshot 925 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 926 aclTable = TEST_UTIL.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME); 927 snapshotAndWait(snapshot, table); 928 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 929 deleteTable(table); 930 deleteTable(table2); 931 } 932 933 static void checkUserAclEntry(FileSystem fs, List<Path> paths, String user, 934 boolean requireAccessAcl, boolean requireDefaultAcl) throws Exception { 935 for (Path path : paths) { 936 checkUserAclEntry(fs, path, user, requireAccessAcl, requireDefaultAcl); 937 } 938 } 939 940 static void checkUserAclEntry(FileSystem fs, Path path, String userName, boolean requireAccessAcl, 941 boolean requireDefaultAcl) throws IOException { 942 boolean accessAclEntry = false; 943 boolean defaultAclEntry = false; 944 if (fs.exists(path)) { 945 for (AclEntry aclEntry : fs.getAclStatus(path).getEntries()) { 946 String user = aclEntry.getName(); 947 if (user != null && user.equals(userName)) { 948 if (aclEntry.getScope() == AclEntryScope.DEFAULT) { 949 defaultAclEntry = true; 950 } else if (aclEntry.getScope() == AclEntryScope.ACCESS) { 951 accessAclEntry = true; 952 } 953 } 954 } 955 } 956 String message = "require user: " + userName + ", path: " + path.toString() + " acl"; 957 assertEquals(requireAccessAcl, accessAclEntry, message); 958 assertEquals(requireDefaultAcl, defaultAclEntry, message); 959 } 960 961 static void deleteTable(TableName tableName) { 962 try { 963 admin.disableTable(tableName); 964 admin.deleteTable(tableName); 965 } catch (IOException e) { 966 LOG.warn("Failed to delete table: {}", tableName); 967 } 968 } 969}