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.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 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 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()), 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 and grantUser3 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 testDeleteNamespace() throws Exception { 678 String grantUserName = name.getMethodName(); 679 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 680 String namespace = name.getMethodName(); 681 TableName table = TableName.valueOf(namespace, name.getMethodName()); 682 String snapshot = namespace + "t1"; 683 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 684 // snapshot 685 snapshotAndWait(snapshot, table); 686 // grant namespace permission 687 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 688 // delete table 689 admin.disableTable(table); 690 admin.deleteTable(table); 691 // delete namespace 692 admin.deleteNamespace(namespace); 693 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 694 assertFalse(hasUserNamespaceHdfsAcl(aclTable, grantUserName, namespace)); 695 checkUserAclEntry(FS, helper.getPathHelper().getArchiveNsDir(namespace), grantUserName, true, 696 false); 697 698 // check tmp namespace dir does not exist 699 assertFalse(FS.exists(helper.getPathHelper().getTmpNsDir(namespace))); 700 assertFalse(FS.exists(helper.getPathHelper().getDataNsDir(namespace))); 701 // assertFalse(fs.exists(FS, helper.getPathHelper().getMobDataNsDir(namespace))); 702 deleteTable(table); 703 } 704 705 @Test 706 public void testCleanArchiveTableDir() throws Exception { 707 final String grantUserName = name.getMethodName(); 708 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 709 String namespace = name.getMethodName(); 710 TableName table = TableName.valueOf(namespace, name.getMethodName()); 711 String snapshot = namespace + "t1"; 712 713 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 714 snapshotAndWait(snapshot, table); 715 TestHDFSAclHelper.grantOnTable(TEST_UTIL, grantUserName, table, READ); 716 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 717 718 // HFileCleaner will not delete archive table directory even if it's a empty directory 719 HFileCleaner cleaner = TEST_UTIL.getHBaseCluster().getMaster().getHFileCleaner(); 720 cleaner.choreForTesting(); 721 Path archiveTableDir = HFileArchiveUtil.getTableArchivePath(rootDir, table); 722 assertTrue(FS.exists(archiveTableDir)); 723 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), grantUserName, true, true); 724 725 // Check SnapshotScannerHDFSAclCleaner method 726 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveTableDir(archiveTableDir)); 727 assertTrue(SnapshotScannerHDFSAclCleaner.isArchiveNamespaceDir(archiveTableDir.getParent())); 728 assertTrue( 729 SnapshotScannerHDFSAclCleaner.isArchiveDataDir(archiveTableDir.getParent().getParent())); 730 assertFalse(SnapshotScannerHDFSAclCleaner 731 .isArchiveDataDir(archiveTableDir.getParent().getParent().getParent())); 732 deleteTable(table); 733 } 734 735 @Test 736 public void testModifyTable1() throws Exception { 737 String namespace = name.getMethodName(); 738 TableName table = TableName.valueOf(namespace, name.getMethodName()); 739 String snapshot = namespace + "t1"; 740 741 String tableUserName = name.getMethodName(); 742 User tableUser = User.createUserForTesting(conf, tableUserName, new String[] {}); 743 String tableUserName2 = tableUserName + "2"; 744 User tableUser2 = User.createUserForTesting(conf, tableUserName2, new String[] {}); 745 String tableUserName3 = tableUserName + "3"; 746 User tableUser3 = User.createUserForTesting(conf, tableUserName3, new String[] {}); 747 String nsUserName = tableUserName + "-ns"; 748 User nsUser = User.createUserForTesting(conf, nsUserName, new String[] {}); 749 String globalUserName = tableUserName + "-global"; 750 User globalUser = User.createUserForTesting(conf, globalUserName, new String[] {}); 751 String globalUserName2 = tableUserName + "-global-2"; 752 User globalUser2 = User.createUserForTesting(conf, globalUserName2, new String[] {}); 753 754 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName, READ); 755 TestHDFSAclHelper.createNamespace(TEST_UTIL, namespace); 756 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsUserName, namespace, READ); 757 TableDescriptor td = TestHDFSAclHelper.createUserScanSnapshotDisabledTable(TEST_UTIL, table); 758 snapshotAndWait(snapshot, table); 759 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName2, READ); 760 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName, table, READ); 761 SecureTestUtil.grantOnTable(TEST_UTIL, tableUserName2, table, TestHDFSAclHelper.COLUMN1, null, 762 READ); 763 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table, WRITE); 764 765 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, -1); 766 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 767 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 768 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, -1); 769 // Global permission is set before table is created, the acl is inherited 770 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 771 // Global permission is set after table is created, the table dir acl is skip 772 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser2, snapshot, -1); 773 774 // enable user scan snapshot 775 admin.modifyTable(TableDescriptorBuilder.newBuilder(td) 776 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "true").build()); 777 // check scan snapshot 778 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, 6); 779 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 780 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 781 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, 6); 782 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, 6); 783 // check acl table storage and ACLs in dirs 784 assertTrue(hasUserGlobalHdfsAcl(aclTable, globalUserName)); 785 checkUserAclEntry(FS, helper.getGlobalRootPaths(), globalUserName, true, true); 786 assertTrue(hasUserNamespaceHdfsAcl(aclTable, nsUserName, namespace)); 787 checkUserAclEntry(FS, helper.getNamespaceRootPaths(namespace), nsUserName, true, true); 788 assertTrue(hasUserTableHdfsAcl(aclTable, tableUserName, table)); 789 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), tableUserName, true, true); 790 for (String user : new String[] { tableUserName2, tableUserName3 }) { 791 assertFalse(hasUserTableHdfsAcl(aclTable, user, table)); 792 checkUserAclEntry(FS, helper.getTableRootPaths(table, false), user, false, false); 793 } 794 deleteTable(table); 795 } 796 797 @Test 798 public void testModifyTable2() throws Exception { 799 String namespace = name.getMethodName(); 800 TableName table = TableName.valueOf(namespace, name.getMethodName() + ".1"); 801 String snapshot = namespace + "t1"; 802 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 803 804 String tableUserName = name.getMethodName(); 805 User tableUser = User.createUserForTesting(conf, tableUserName, new String[] {}); 806 String tableUserName2 = tableUserName + "2"; 807 User tableUser2 = User.createUserForTesting(conf, tableUserName2, new String[] {}); 808 String tableUserName3 = tableUserName + "3"; 809 User tableUser3 = User.createUserForTesting(conf, tableUserName3, new String[] {}); 810 String nsUserName = tableUserName + "-ns"; 811 User nsUser = User.createUserForTesting(conf, nsUserName, new String[] {}); 812 String globalUserName = tableUserName + "-global"; 813 User globalUser = User.createUserForTesting(conf, globalUserName, new String[] {}); 814 String globalUserName2 = tableUserName + "-global-2"; 815 User globalUser2 = User.createUserForTesting(conf, globalUserName2, new String[] {}); 816 817 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 818 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName, READ); 819 SecureTestUtil.grantGlobal(TEST_UTIL, globalUserName2, READ); 820 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsUserName, namespace, READ); 821 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName, table, READ); 822 SecureTestUtil.grantOnTable(TEST_UTIL, tableUserName2, table, TestHDFSAclHelper.COLUMN1, null, 823 READ); 824 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table, WRITE); 825 826 SecureTestUtil.grantOnNamespace(TEST_UTIL, tableUserName2, namespace, READ); 827 TestHDFSAclHelper.createTable(TEST_UTIL, table2); 828 TestHDFSAclHelper.grantOnTable(TEST_UTIL, tableUserName3, table2, READ); 829 // disable user scan snapshot 830 admin.modifyTable(TableDescriptorBuilder.newBuilder(admin.getDescriptor(table)) 831 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "false").build()); 832 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser, snapshot, -1); 833 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser2, snapshot, -1); 834 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, tableUser3, snapshot, -1); 835 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, nsUser, snapshot, -1); 836 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser, snapshot, -1); 837 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, globalUser2, snapshot, -1); 838 // check access 839 String[] users = new String[] { globalUserName, globalUserName2, nsUserName, tableUserName, 840 tableUserName2, tableUserName3 }; 841 for (Path path : helper.getTableRootPaths(table, false)) { 842 for (String user : users) { 843 checkUserAclEntry(FS, path, user, false, false); 844 } 845 } 846 String[] nsUsers = new String[] { globalUserName, globalUserName2, nsUserName }; 847 for (Path path : helper.getNamespaceRootPaths(namespace)) { 848 checkUserAclEntry(FS, path, tableUserName, false, false); 849 checkUserAclEntry(FS, path, tableUserName2, true, true); 850 checkUserAclEntry(FS, path, tableUserName3, true, false); 851 for (String user : nsUsers) { 852 checkUserAclEntry(FS, path, user, true, true); 853 } 854 } 855 assertTrue(hasUserNamespaceHdfsAcl(aclTable, nsUserName, namespace)); 856 assertTrue(hasUserNamespaceHdfsAcl(aclTable, tableUserName2, namespace)); 857 assertFalse(hasUserTableHdfsAcl(aclTable, tableUserName, table)); 858 deleteTable(table); 859 deleteTable(table2); 860 } 861 862 @Test 863 public void testRestartMaster() throws Exception { 864 final String grantUserName = name.getMethodName(); 865 User grantUser = User.createUserForTesting(conf, grantUserName, new String[] {}); 866 String namespace = name.getMethodName(); 867 TableName table = TableName.valueOf(namespace, name.getMethodName() + ".1"); 868 TableName table2 = TableName.valueOf(namespace, name.getMethodName() + ".2"); 869 String snapshot = namespace + "t1"; 870 admin.createNamespace(NamespaceDescriptor.create(namespace).build()); 871 872 // create table2 873 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table2); 874 // make some region files in tmp dir and check if master archive these region correctly 875 Path tmpTableDir = helper.getPathHelper().getTmpTableDir(table2); 876 // make a empty region dir, this is an error region 877 FS.mkdirs(new Path(tmpTableDir, "1")); 878 // copy regions from data dir, this is a valid region 879 for (Path regionDir : FSUtils.getRegionDirs(FS, 880 helper.getPathHelper().getDataTableDir(table2))) { 881 FSUtils.copyFilesParallel(FS, regionDir, FS, 882 new Path(tmpTableDir, regionDir.getName() + "abc"), conf, 1); 883 } 884 assertEquals(4, FS.listStatus(tmpTableDir).length); 885 886 // grant N(R) 887 SecureTestUtil.grantOnNamespace(TEST_UTIL, grantUserName, namespace, READ); 888 // restart cluster and tmp directory will not be deleted 889 TEST_UTIL.getMiniHBaseCluster().shutdown(); 890 TEST_UTIL.restartHBaseCluster(1); 891 TEST_UTIL.waitUntilNoRegionsInTransition(); 892 893 // reset the cached configs after restart 894 conf = TEST_UTIL.getConfiguration(); 895 admin = TEST_UTIL.getAdmin(); 896 helper = new SnapshotScannerHDFSAclHelper(conf, admin.getConnection()); 897 898 Path tmpNsDir = helper.getPathHelper().getTmpNsDir(namespace); 899 assertTrue(FS.exists(tmpNsDir)); 900 // check all regions in tmp table2 dir are archived 901 assertEquals(0, FS.listStatus(tmpTableDir).length); 902 903 // create table1 and snapshot 904 TestHDFSAclHelper.createTableAndPut(TEST_UTIL, table); 905 aclTable = TEST_UTIL.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME); 906 snapshotAndWait(snapshot, table); 907 TestHDFSAclHelper.canUserScanSnapshot(TEST_UTIL, grantUser, snapshot, 6); 908 deleteTable(table); 909 deleteTable(table2); 910 } 911 912 static void checkUserAclEntry(FileSystem fs, List<Path> paths, String user, 913 boolean requireAccessAcl, boolean requireDefaultAcl) throws Exception { 914 for (Path path : paths) { 915 checkUserAclEntry(fs, path, user, requireAccessAcl, requireDefaultAcl); 916 } 917 } 918 919 static void checkUserAclEntry(FileSystem fs, Path path, String userName, boolean requireAccessAcl, 920 boolean requireDefaultAcl) throws IOException { 921 boolean accessAclEntry = false; 922 boolean defaultAclEntry = false; 923 if (fs.exists(path)) { 924 for (AclEntry aclEntry : fs.getAclStatus(path).getEntries()) { 925 String user = aclEntry.getName(); 926 if (user != null && user.equals(userName)) { 927 if (aclEntry.getScope() == AclEntryScope.DEFAULT) { 928 defaultAclEntry = true; 929 } else if (aclEntry.getScope() == AclEntryScope.ACCESS) { 930 accessAclEntry = true; 931 } 932 } 933 } 934 } 935 String message = "require user: " + userName + ", path: " + path.toString() + " acl"; 936 assertEquals(message, requireAccessAcl, accessAclEntry); 937 assertEquals(message, requireDefaultAcl, defaultAclEntry); 938 } 939 940 static void deleteTable(TableName tableName) { 941 try { 942 admin.disableTable(tableName); 943 admin.deleteTable(tableName); 944 } catch (IOException e) { 945 LOG.warn("Failed to delete table: {}", tableName); 946 } 947 } 948}