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.Assert.assertEquals; 026import static org.junit.Assert.assertFalse; 027import static org.junit.Assert.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.HBaseClassTestRule; 038import org.apache.hadoop.hbase.HBaseTestingUtil; 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 HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 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 SnapshotScannerHDFSAclController coprocessor = TEST_UTIL.getHBaseCluster().getMaster() 102 .getMasterCoprocessorHost().findCoprocessor(SnapshotScannerHDFSAclController.class); 103 TEST_UTIL.waitFor(30000, () -> coprocessor.checkInitialized("check initialized")); 104 TEST_UTIL.waitTableAvailable(PermissionStorage.ACL_TABLE_NAME); 105 106 admin = TEST_UTIL.getAdmin(); 107 rootDir = TEST_UTIL.getDefaultRootDirPath(); 108 FS = rootDir.getFileSystem(conf); 109 unGrantUser = User.createUserForTesting(conf, UN_GRANT_USER, new String[] {}); 110 helper = new SnapshotScannerHDFSAclHelper(conf, admin.getConnection()); 111 112 // set hbase directory permission 113 FsPermission commonDirectoryPermission = 114 new FsPermission(conf.get(SnapshotScannerHDFSAclHelper.COMMON_DIRECTORY_PERMISSION, 115 SnapshotScannerHDFSAclHelper.COMMON_DIRECTORY_PERMISSION_DEFAULT)); 116 Path path = rootDir; 117 while (path != null) { 118 FS.setPermission(path, commonDirectoryPermission); 119 path = path.getParent(); 120 } 121 // set restore directory permission 122 Path restoreDir = new Path(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_TMP_DIR_DEFAULT); 123 if (!FS.exists(restoreDir)) { 124 FS.mkdirs(restoreDir); 125 FS.setPermission(restoreDir, 126 new FsPermission( 127 conf.get(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_DIRECTORY_PERMISSION, 128 SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_DIRECTORY_PERMISSION_DEFAULT))); 129 } 130 path = restoreDir.getParent(); 131 while (path != null) { 132 FS.setPermission(path, commonDirectoryPermission); 133 path = path.getParent(); 134 } 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 three seconds, 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()), false); 202 // grant G(W) 203 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, WRITE); 204 // create table in namespace2 and snapshot 205 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 206 snapshotAndWait(snapshot2, table2); 207 // check scan snapshot 208 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 209 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, -1); 210 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 211 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace1)); 212 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace2)); 213 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 214 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace1), grantUserName, true, true); 215 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace2), grantUserName, false, false); 216 deleteTable(table1); 217 deleteTable(table2); 218 } 219 220 @Test 221 public void testGrantGlobal3() throws Exception { 222 final String grantUserName = name.getMethodName(); 223 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 224 String namespace = name.getMethodName(); 225 TableName table1 = TableName.valueOf(namespace, name.getMethodName() + ".1"); 226 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 227 String snapshot1 = namespace + "s1"; 228 String snapshot2 = namespace + "s2"; 229 // grant G(R) 230 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 231 // grant table1(R) 232 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 233 snapshotAndWait(snapshot1, table1); 234 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 235 // grant G(W) 236 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, WRITE); 237 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 238 snapshotAndWait(snapshot2, table2); 239 // check scan snapshot 240 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 241 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, -1); 242 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 243 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 244 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 245 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table2)); 246 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 247 checkUserAclEntry(FS, helper.getTableRootPaths(table2, false), grantUserName, false, false); 248 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 249 deleteTable(table1); 250 deleteTable(table2); 251 } 252 253 @Test 254 public void testGrantNamespace1() throws Exception { 255 final String grantUserName = name.getMethodName(); 256 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 257 String namespace = name.getMethodName(); 258 TableName table1 = TableName.valueOf(namespace, name.getMethodName() + ".1"); 259 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 260 String snapshot1 = namespace + "s1"; 261 String snapshot2 = namespace + "s2"; 262 263 // create table1 and snapshot 264 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 265 snapshotAndWait(snapshot1, table1); 266 // grant N(R) 267 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 268 // create table2 and snapshot, ACLs can be inherited automatically 269 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 270 snapshotAndWait(snapshot2, table2); 271 // check scan snapshot 272 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 273 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 6); 274 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, unGrantUser, snapshot1, -1); 275 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 276 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 277 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 278 // grant N(W) 279 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 280 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 281 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 282 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, false, false); 283 deleteTable(table1); 284 deleteTable(table2); 285 } 286 287 @Test 288 public void testGrantNamespace2() throws Exception { 289 final String grantUserName = name.getMethodName(); 290 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 291 String namespace = name.getMethodName(); 292 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 293 String snapshot1 = namespace + "s1"; 294 295 // create table1 and snapshot 296 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 297 snapshotAndWait(snapshot1, table1); 298 299 // grant N(R) 300 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 301 // grant table1(R) 302 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 303 // grant N(W) 304 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 305 // check scan snapshot 306 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 307 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 308 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 309 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 310 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 311 deleteTable(table1); 312 } 313 314 @Test 315 public void testGrantNamespace3() throws Exception { 316 final String grantUserName = name.getMethodName(); 317 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 318 String namespace = name.getMethodName(); 319 TableName table = TableName.valueOf(namespace, name.getMethodName()); 320 String snapshot = namespace + "t1"; 321 322 // create table1 and snapshot 323 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 324 snapshotAndWait(snapshot, table); 325 // grant namespace(R) 326 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 327 // grant global(R) 328 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 329 // grant namespace(W) 330 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, WRITE); 331 // check scan snapshot 332 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 333 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 334 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 335 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 336 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, true, true); 337 deleteTable(table); 338 } 339 340 @Test 341 public void testGrantTable() throws Exception { 342 final String grantUserName = name.getMethodName(); 343 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 344 345 String namespace = name.getMethodName(); 346 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 347 String snapshot1 = namespace + "s1"; 348 String snapshot2 = namespace + "s2"; 349 350 LOG.info("Create table"); 351 try (Table t = TestHDFSAclHelper.createTable(TEST_UTIL, table1)) { 352 TestHDFSAclHelper.put(t); 353 snapshotAndWait(snapshot1, table1); 354 // table owner can scan table snapshot 355 LOG.info("Scan snapshot"); 356 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, 357 User.createUserForTesting(conf, "owner", new String[] {}), snapshot1, 6); 358 // grant table1 family(R) 359 SecureTestUtil.grantOnTable(TEST_UTIL, grantUserName, table1, TestHDFSAclHelper.COLUMN1, null, 360 READ); 361 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 362 363 // grant table1(R) 364 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 365 TestHDFSAclHelper.put2(t); 366 snapshotAndWait(snapshot2, table1); 367 368 // check scan snapshot 369 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 370 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 10); 371 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 372 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 373 } 374 375 // grant table1(W) with merging existing permissions 376 admin.grant( 377 new UserPermission(grantUserName, Permission.newBuilder(table1).withActions(WRITE).build()), 378 true); 379 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 380 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 381 382 // grant table1(W) without merging existing permissions 383 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, WRITE); 384 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 385 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 386 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, false, false); 387 deleteTable(table1); 388 } 389 390 @Test 391 public void testGrantMobTable() throws Exception { 392 final String grantUserName = name.getMethodName(); 393 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 394 String namespace = name.getMethodName(); 395 TableName table = TableName.valueOf(namespace, name.getMethodName()); 396 String snapshot = namespace + "s1"; 397 398 try (Table t = TestHDFSAclHelper.createMobTable(TEST_UTIL, table)) { 399 TestHDFSAclHelper.put(t); 400 snapshotAndWait(snapshot, table); 401 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 402 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 403 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 404 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 405 } 406 deleteTable(table); 407 } 408 409 @Test 410 public void testRevokeGlobal1() throws Exception { 411 final String grantUserName = name.getMethodName(); 412 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 413 String namespace = name.getMethodName(); 414 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 415 String snapshot1 = namespace + "t1"; 416 417 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 418 snapshotAndWait(snapshot1, table1); 419 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 420 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 421 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 422 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 423 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 424 deleteTable(table1); 425 } 426 427 @Test 428 public void testRevokeGlobal2() throws Exception { 429 final String grantUserName = name.getMethodName(); 430 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 431 432 String namespace = name.getMethodName(); 433 String snapshot1 = namespace + "s1"; 434 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 435 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 436 snapshotAndWait(snapshot1, table1); 437 438 // grant G(R), grant N(R), grant T(R) -> revoke G(R) 439 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 440 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 441 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 442 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 443 // check scan snapshot 444 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 445 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 446 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 447 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 448 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 449 deleteTable(table1); 450 } 451 452 @Test 453 public void testRevokeGlobal3() throws Exception { 454 final String grantUserName = name.getMethodName(); 455 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 456 457 String namespace = name.getMethodName(); 458 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 459 String snapshot1 = namespace + "t1"; 460 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 461 snapshotAndWait(snapshot1, table1); 462 463 // grant G(R), grant T(R) -> revoke G(R) 464 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 465 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table1, READ); 466 SecureTestUtil.revokeGlobal(TEST_UTIL, grantUserName, READ); 467 // check scan snapshot 468 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 469 assertFalse(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 470 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, false, false); 471 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 472 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 473 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table1)); 474 checkUserAclEntry(FS, helper.getTableRootPaths(table1, false), grantUserName, true, true); 475 deleteTable(table1); 476 } 477 478 @Test 479 public void testRevokeNamespace1() throws Exception { 480 String grantUserName = name.getMethodName(); 481 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 482 String namespace = name.getMethodName(); 483 TableName table1 = TableName.valueOf(namespace, name.getMethodName()); 484 String snapshot1 = namespace + "s1"; 485 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table1); 486 snapshotAndWait(snapshot1, table1); 487 488 // revoke N(R) 489 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 490 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(namespace).build())); 491 // check scan snapshot 492 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, -1); 493 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 494 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, false, false); 495 496 // grant N(R), grant G(R) -> revoke N(R) 497 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 498 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 499 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(namespace).build())); 500 // check scan snapshot 501 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot1, 6); 502 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 503 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 504 deleteTable(table1); 505 } 506 507 @Test 508 public void testRevokeNamespace2() throws Exception { 509 String grantUserName = name.getMethodName(); 510 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 511 String namespace = name.getMethodName(); 512 TableName table = TableName.valueOf(namespace, name.getMethodName()); 513 String snapshot = namespace + "s1"; 514 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 515 snapshotAndWait(snapshot, table); 516 517 // grant N(R), grant T(R) -> revoke N(R) 518 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 519 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 520 SecureTestUtil.revokeFromNamespace(TEST_UTIL, grantUserName, namespace, READ); 521 // check scan snapshot 522 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 523 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 524 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 525 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 526 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 527 deleteTable(table); 528 } 529 530 @Test 531 public void testRevokeTable1() throws Exception { 532 final String grantUserName = name.getMethodName(); 533 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 534 String namespace = name.getMethodName(); 535 TableName table = TableName.valueOf(namespace, name.getMethodName()); 536 String snapshot = namespace + "t1"; 537 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 538 snapshotAndWait(snapshot, table); 539 540 // grant T(R) -> revoke table family 541 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 542 SecureTestUtil.revokeFromTable(TEST_UTIL, grantUserName, table, TestHDFSAclHelper.COLUMN1, null, 543 READ); 544 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 545 546 // grant T(R) -> revoke T(R) 547 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 548 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 549 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, -1); 550 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 551 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, false, false); 552 deleteTable(table); 553 } 554 555 @Test 556 public void testRevokeTable2() throws Exception { 557 final String grantUserName = name.getMethodName(); 558 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 559 String namespace = name.getMethodName(); 560 TableName table = TableName.valueOf(namespace, name.getMethodName()); 561 String snapshot = namespace + "t1"; 562 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 563 snapshotAndWait(snapshot, table); 564 565 // grant T(R), grant N(R) -> revoke T(R) 566 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 567 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 568 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 569 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 570 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 571 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 572 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 573 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, true); 574 deleteTable(table); 575 } 576 577 @Test 578 public void testRevokeTable3() throws Exception { 579 final String grantUserName = name.getMethodName(); 580 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 581 String namespace = name.getMethodName(); 582 TableName table = TableName.valueOf(namespace, name.getMethodName()); 583 String snapshot = namespace + "t1"; 584 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 585 snapshotAndWait(snapshot, table); 586 587 // grant T(R), grant G(R) -> revoke T(R) 588 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 589 SecureTestUtil.grantGlobal(TEST_UTIL, grantUserName, READ); 590 admin.revoke(new UserPermission(grantUserName, Permission.newBuilder(table).build())); 591 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 592 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName, table)); 593 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 594 assertTrue(hasUserGlobalHdfsAcl(aclTable, grantUserName)); 595 checkUserAclEntry(FS, helper.getGlobalRootPaths(), grantUserName, true, true); 596 deleteTable(table); 597 } 598 599 @Test 600 public void testTruncateTable() throws Exception { 601 String grantUserName = name.getMethodName(); 602 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 603 String grantUserName2 = grantUserName + "2"; 604 User grantUser2 = User.createUserForTesting(conf, grantUserName2, new String[] {}); 605 606 String namespace = name.getMethodName(); 607 TableName tableName = TableName.valueOf(namespace, name.getMethodName()); 608 String snapshot = namespace + "s1"; 609 String snapshot2 = namespace + "s2"; 610 try (Table t = TestHDFSAclHelper.createTable(TEST_UTIL, tableName)) { 611 TestHDFSAclHelper.put(t); 612 // snapshot 613 snapshotAndWait(snapshot, tableName); 614 // grant user2 namespace permission 615 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName2, namespace, READ); 616 // grant user table permission 617 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, tableName, READ); 618 // truncate table 619 admin.disableTable(tableName); 620 admin.truncateTable(tableName, true); 621 TestHDFSAclHelper.put2(t); 622 // snapshot 623 snapshotAndWait(snapshot2, tableName); 624 // check scan snapshot 625 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 626 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot, 6); 627 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot2, 9); 628 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot2, 9); 629 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName2, namespace)); 630 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName2, true, true); 631 assertTrue(hasUserTableHdfsAcl(aclTable, grantUserName, tableName)); 632 checkUserAclEntry(FS, helper.getTableRootPaths(tableName, false), grantUserName, true, true); 633 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName, true, false); 634 } 635 deleteTable(tableName); 636 } 637 638 @Test 639 public void testDeleteTable() throws Exception { 640 String namespace = name.getMethodName(); 641 String grantUserName1 = namespace + "1"; 642 String grantUserName2 = namespace + "2"; 643 User grantUser1 = User.createUserForTesting(conf, grantUserName1, new String[] {}); 644 User grantUser2 = User.createUserForTesting(conf, grantUserName2, new String[] {}); 645 TableName table = TableName.valueOf(namespace, name.getMethodName()); 646 String snapshot1 = namespace + "t1"; 647 648 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 649 // snapshot 650 snapshotAndWait(snapshot1, table); 651 // grant user table permission 652 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName1, table, READ); 653 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName2, namespace, READ); 654 // delete table 655 admin.disableTable(table); 656 admin.deleteTable(table); 657 // grantUser2 should have data/ns acl 658 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser1, snapshot1, -1); 659 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser2, snapshot1, 6); 660 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUserName2, namespace)); 661 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), grantUserName2, true, true); 662 assertFalse(hasUserTableHdfsAcl(aclTable, grantUserName1, table)); 663 checkUserAclEntry(FS, helper.getPathHelper().getDataTableDir(table), grantUserName1, false, 664 false); 665 checkUserAclEntry(FS, helper.getPathHelper().getMobTableDir(table), grantUserName1, false, 666 false); 667 checkUserAclEntry(FS, helper.getPathHelper().getArchiveTableDir(table), grantUserName1, true, 668 false); 669 670 // check tmp table directory does not exist 671 Path tmpTableDir = helper.getPathHelper().getTmpTableDir(table); 672 assertFalse(FS.exists(tmpTableDir)); 673 deleteTable(table); 674 } 675 676 @Test 677 public void testDeleteTable2() throws Exception { 678 String namespace1 = name.getMethodName() + "1"; 679 String namespace2 = name.getMethodName() + "2"; 680 String grantUser = name.getMethodName(); 681 TableName table = TableName.valueOf(namespace1, name.getMethodName()); 682 683 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 684 // grant user table permission 685 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUser, table, READ); 686 // grant user other namespace permission 687 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUser, namespace2, READ); 688 // delete table 689 admin.disableTable(table); 690 admin.deleteTable(table); 691 // grantUser should have namespace2's acl 692 assertFalse(hasUserTableHdfsAcl(aclTable, grantUser, table)); 693 assertTrue(hasUserNamespaceHdfsAcl(aclTable, grantUser, namespace2)); 694 } 695 696 @Test 697 public void testDeleteNamespace() throws Exception { 698 String grantUserName = name.getMethodName(); 699 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 700 String namespace = name.getMethodName(); 701 TableName table = TableName.valueOf(namespace, name.getMethodName()); 702 String snapshot = namespace + "t1"; 703 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 704 // snapshot 705 snapshotAndWait(snapshot, table); 706 // grant namespace permission 707 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 708 // delete table 709 admin.disableTable(table); 710 admin.deleteTable(table); 711 // delete namespace 712 admin.deleteNamespace(namespace); 713 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 714 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 715 checkUserAclEntry(FS, helper.getPathHelper().getArchiveNsDir(namespace), grantUserName, true, 716 false); 717 718 // check tmp namespace dir does not exist 719 assertFalse(FS.exists(helper.getPathHelper().getTmpNsDir(namespace))); 720 assertFalse(FS.exists(helper.getPathHelper().getDataNsDir(namespace))); 721 // assertFalse(fs.exists(FS, helper.getPathHelper().getMobDataNsDir(namespace))); 722 deleteTable(table); 723 } 724 725 @Test 726 public void testCleanArchiveTableDir() throws Exception { 727 final String grantUserName = name.getMethodName(); 728 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 729 String namespace = name.getMethodName(); 730 TableName table = TableName.valueOf(namespace, name.getMethodName()); 731 String snapshot = namespace + "t1"; 732 733 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 734 snapshotAndWait(snapshot, table); 735 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 736 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 737 738 // HFileCleaner will not delete archive table directory even if it's a empty directory 739 HFileCleaner cleaner = TEST_UTIL.getHBaseCluster().getMaster().getHFileCleaner(); 740 cleaner.choreForTesting(); 741 Path archiveTableDir = HFileArchiveUtil.getTableArchivePath(rootDir, table); 742 assertTrue(FS.exists(archiveTableDir)); 743 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 744 745 // Check SnapshotScannerHDFSAclCleaner method 746 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveTableDir(archiveTableDir)); 747 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveNamespaceDir(archiveTableDir.getParent())); 748 assertTrue( 749 SnapshotScannerHDFSAclCleaner.isArchiveDataDir(archiveTableDir.getParent().getParent())); 750 assertFalse(SnapshotScannerHDFSAclCleaner 751 .isArchiveDataDir(archiveTableDir.getParent().getParent().getParent())); 752 deleteTable(table); 753 } 754 755 @Test 756 public void testModifyTable1() throws Exception { 757 String namespace = name.getMethodName(); 758 TableName table = TableName.valueOf(namespace, name.getMethodName()); 759 String snapshot = namespace + "t1"; 760 761 String tableUserName = name.getMethodName(); 762 User tableUser = User.createUserForTesting(conf, tableUserName, new String[] {}); 763 String tableUserName2 = tableUserName + "2"; 764 User tableUser2 = User.createUserForTesting(conf, tableUserName2, new String[] {}); 765 String tableUserName3 = tableUserName + "3"; 766 User tableUser3 = User.createUserForTesting(conf, tableUserName3, new String[] {}); 767 String nsUserName = tableUserName + "-ns"; 768 User nsUser = User.createUserForTesting(conf, nsUserName, new String[] {}); 769 String globalUserName = tableUserName + "-global"; 770 User globalUser = User.createUserForTesting(conf, globalUserName, new String[] {}); 771 String globalUserName2 = tableUserName + "-global-2"; 772 User globalUser2 = User.createUserForTesting(conf, globalUserName2, new String[] {}); 773 774 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName, READ); 775 TestHDFSAclHelper.createNamespace(TEST_UTIL, namespace); 776 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsUserName, namespace, READ); 777 TableDescriptor td = TestHDFSAclHelper.createUserScanSnapshotDisabledTable(TEST_UTIL, table); 778 snapshotAndWait(snapshot, table); 779 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName2, READ); 780 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName, table, READ); 781 SecureTestUtil.grantOnTable(TEST_UTIL, tableUserName2, table, TestHDFSAclHelper.COLUMN1, null, 782 READ); 783 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table, WRITE); 784 785 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, -1); 786 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 787 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 788 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, -1); 789 // Global permission is set before table is created, the acl is inherited 790 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 791 // Global permission is set after table is created, the table dir acl is skip 792 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser2, snapshot, -1); 793 794 // enable user scan snapshot 795 admin.modifyTable(TableDescriptorBuilder.newBuilder(td) 796 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "true").build()); 797 // check scan snapshot 798 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, 6); 799 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 800 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 801 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, 6); 802 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 803 // check acl table storage and ACLs in dirs 804 assertTrue(hasUserGlobalHdfsAcl(aclTable, globalUserName)); 805 checkUserAclEntry(FS, helper.getGlobalRootPaths(), globalUserName, true, true); 806 assertTrue(hasUserNamespaceHdfsAcl(aclTable, nsUserName, namespace)); 807 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), nsUserName, true, true); 808 assertTrue(hasUserTableHdfsAcl(aclTable, tableUserName, table)); 809 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), tableUserName, true, true); 810 for (String user : new String[] { tableUserName2, tableUserName3 }) { 811 assertFalse(hasUserTableHdfsAcl(aclTable, user, table)); 812 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), user, false, false); 813 } 814 deleteTable(table); 815 } 816 817 @Test 818 public void testModifyTable2() throws Exception { 819 String namespace = name.getMethodName(); 820 TableName table = TableName.valueOf(namespace, name.getMethodName() + ".1"); 821 String snapshot = namespace + "t1"; 822 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 823 824 String tableUserName = name.getMethodName(); 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() throws Exception { 884 final String grantUserName = name.getMethodName(); 885 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 886 String namespace = name.getMethodName(); 887 TableName table = TableName.valueOf(namespace, name.getMethodName() + ".1"); 888 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 889 String snapshot = namespace + "t1"; 890 admin.createNamespace(NamespaceDescriptor.create(namespace).build()); 891 892 // create table2 893 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 894 // make some region files in tmp dir and check if master archive these region correctly 895 Path tmpTableDir = helper.getPathHelper().getTmpTableDir(table2); 896 // make a empty region dir, this is an error region 897 FS.mkdirs(new Path(tmpTableDir, "1")); 898 // copy regions from data dir, this is a valid region 899 for (Path regionDir : FSUtils.getRegionDirs(FS, 900 helper.getPathHelper().getDataTableDir(table2))) { 901 FSUtils.copyFilesParallel(FS, regionDir, FS, 902 new Path(tmpTableDir, regionDir.getName() + "abc"), conf, 1); 903 } 904 assertEquals(4, FS.listStatus(tmpTableDir).length); 905 906 // grant N(R) 907 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 908 // restart cluster and tmp directory will not be deleted 909 TEST_UTIL.getMiniHBaseCluster().shutdown(); 910 TEST_UTIL.restartHBaseCluster(1); 911 TEST_UTIL.waitUntilNoRegionsInTransition(); 912 913 // reset the cached configs after restart 914 conf = TEST_UTIL.getConfiguration(); 915 admin = TEST_UTIL.getAdmin(); 916 helper = new SnapshotScannerHDFSAclHelper(conf, admin.getConnection()); 917 918 Path tmpNsDir = helper.getPathHelper().getTmpNsDir(namespace); 919 assertTrue(FS.exists(tmpNsDir)); 920 // check all regions in tmp table2 dir are archived 921 assertEquals(0, FS.listStatus(tmpTableDir).length); 922 923 // create table1 and snapshot 924 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 925 aclTable = TEST_UTIL.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME); 926 snapshotAndWait(snapshot, table); 927 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 928 deleteTable(table); 929 deleteTable(table2); 930 } 931 932 static void checkUserAclEntry(FileSystem fs, List<Path> paths, String user, 933 boolean requireAccessAcl, boolean requireDefaultAcl) throws Exception { 934 for (Path path : paths) { 935 checkUserAclEntry(fs, path, user, requireAccessAcl, requireDefaultAcl); 936 } 937 } 938 939 static void checkUserAclEntry(FileSystem fs, Path path, String userName, boolean requireAccessAcl, 940 boolean requireDefaultAcl) throws IOException { 941 boolean accessAclEntry = false; 942 boolean defaultAclEntry = false; 943 if (fs.exists(path)) { 944 for (AclEntry aclEntry : fs.getAclStatus(path).getEntries()) { 945 String user = aclEntry.getName(); 946 if (user != null && user.equals(userName)) { 947 if (aclEntry.getScope() == AclEntryScope.DEFAULT) { 948 defaultAclEntry = true; 949 } else if (aclEntry.getScope() == AclEntryScope.ACCESS) { 950 accessAclEntry = true; 951 } 952 } 953 } 954 } 955 String message = "require user: " + userName + ", path: " + path.toString() + " acl"; 956 assertEquals(message, requireAccessAcl, accessAclEntry); 957 assertEquals(message, requireDefaultAcl, defaultAclEntry); 958 } 959 960 static void deleteTable(TableName tableName) { 961 try { 962 admin.disableTable(tableName); 963 admin.deleteTable(tableName); 964 } catch (IOException e) { 965 LOG.warn("Failed to delete table: {}", tableName); 966 } 967 } 968}