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