View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.access;
19  
20  import static org.junit.Assert.*;
21  
22  import java.util.Arrays;
23  import java.util.List;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.AuthUtil;
29  import org.apache.hadoop.hbase.Coprocessor;
30  import org.apache.hadoop.hbase.HBaseTestingUtility;
31  import org.apache.hadoop.hbase.HColumnDescriptor;
32  import org.apache.hadoop.hbase.HTableDescriptor;
33  import org.apache.hadoop.hbase.NamespaceDescriptor;
34  import org.apache.hadoop.hbase.TableName;
35  import org.apache.hadoop.hbase.TableNotFoundException;
36  import org.apache.hadoop.hbase.client.HBaseAdmin;
37  import org.apache.hadoop.hbase.client.HTable;
38  import org.apache.hadoop.hbase.client.Put;
39  import org.apache.hadoop.hbase.client.Result;
40  import org.apache.hadoop.hbase.client.ResultScanner;
41  import org.apache.hadoop.hbase.client.Scan;
42  import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
43  import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment;
44  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
45  import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
46  import org.apache.hadoop.hbase.security.User;
47  import org.apache.hadoop.hbase.security.access.Permission.Action;
48  import org.apache.hadoop.hbase.testclassification.LargeTests;
49  import org.apache.hadoop.hbase.util.Bytes;
50  import org.apache.hadoop.hbase.util.TestTableName;
51  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
52  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
53  import org.junit.After;
54  import org.junit.AfterClass;
55  import org.junit.Before;
56  import org.junit.BeforeClass;
57  import org.junit.Rule;
58  import org.junit.Test;
59  import org.junit.experimental.categories.Category;
60  
61  @Category(LargeTests.class)
62  public class TestAccessController2 extends SecureTestUtil {
63    private static final Log LOG = LogFactory.getLog(TestAccessController2.class);
64  
65    private static final byte[] TEST_ROW = Bytes.toBytes("test");
66    private static final byte[] TEST_FAMILY = Bytes.toBytes("f");
67    private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q");
68    private static final byte[] TEST_VALUE = Bytes.toBytes("value");
69  
70    private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
71    private static Configuration conf;
72  
73    private final static byte[] Q1 = Bytes.toBytes("q1");
74    private final static byte[] value1 = Bytes.toBytes("value1");
75  
76    private static byte[] TEST_FAMILY_2 = Bytes.toBytes("f2");
77    private static byte[] TEST_ROW_2 = Bytes.toBytes("r2");
78    private final static byte[] Q2 = Bytes.toBytes("q2");
79    private final static byte[] value2 = Bytes.toBytes("value2");
80  
81    private static byte[] TEST_ROW_3 = Bytes.toBytes("r3");
82  
83    private static final String TESTGROUP_1 = "testgroup_1";
84    private static final String TESTGROUP_2 = "testgroup_2";
85  
86    private static User TESTGROUP1_USER1;
87    private static User TESTGROUP2_USER1;
88  
89    @Rule
90    public TestTableName TEST_TABLE = new TestTableName();
91    private String namespace = "testNamespace";
92    private String tname = namespace + ":testtable1";
93    private byte[] tableName = Bytes.toBytes(tname);
94    private static String TESTGROUP_1_NAME;
95  
96    @BeforeClass
97    public static void setupBeforeClass() throws Exception {
98      conf = TEST_UTIL.getConfiguration();
99      // Enable security
100     enableSecurity(conf);
101     // Verify enableSecurity sets up what we require
102     verifyConfiguration(conf);
103     TEST_UTIL.startMiniCluster();
104     // Wait for the ACL table to become available
105     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
106 
107     TESTGROUP_1_NAME = AuthUtil.toGroupEntry(TESTGROUP_1);
108     TESTGROUP1_USER1 =
109         User.createUserForTesting(conf, "testgroup1_user1", new String[] { TESTGROUP_1 });
110     TESTGROUP2_USER1 =
111         User.createUserForTesting(conf, "testgroup2_user2", new String[] { TESTGROUP_2 });
112   }
113 
114   @Before
115   public void setUp() throws Exception {
116     TEST_UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(namespace).build());
117     HTable table = null;
118     try {
119       table =
120           TEST_UTIL.createTable(TableName.valueOf(tableName),
121             new String[] { Bytes.toString(TEST_FAMILY), Bytes.toString(TEST_FAMILY_2) });
122 
123       // Ingesting test data.
124       table.put(Arrays.asList(new Put(TEST_ROW).add(TEST_FAMILY, Q1, value1),
125           new Put(TEST_ROW_2).add(TEST_FAMILY, Q2, value2),
126           new Put(TEST_ROW_3).add(TEST_FAMILY_2, Q1, value1)));
127     } finally {
128       table.close();
129     }
130 
131     assertEquals(1, AccessControlLists.getTablePermissions(conf, TableName.valueOf(tableName))
132         .size());
133     try {
134       assertEquals(1, AccessControlClient.getUserPermissions(conf, tableName.toString()).size());
135     } catch (Throwable e) {
136       LOG.error("Error during call of AccessControlClient.getUserPermissions. ", e);
137     }
138   }
139 
140   @AfterClass
141   public static void tearDownAfterClass() throws Exception {
142     TEST_UTIL.shutdownMiniCluster();
143   }
144 
145   @After
146   public void tearDown() throws Exception {
147     // Clean the _acl_ table
148     try {
149       TEST_UTIL.deleteTable(tableName);
150     } catch (TableNotFoundException ex) {
151       // Test deleted the table, no problem
152       LOG.info("Test deleted table " + tableName);
153     }
154     TEST_UTIL.getHBaseAdmin().deleteNamespace(namespace);
155     // Verify all table/namespace permissions are erased
156     assertEquals(0, AccessControlLists.getTablePermissions(conf, TableName.valueOf(tableName))
157         .size());
158     assertEquals(0, AccessControlLists.getNamespacePermissions(conf, namespace).size());
159   }
160 
161   @Test
162   public void testCreateWithCorrectOwner() throws Exception {
163     // Create a test user
164     User testUser =
165         User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser", new String[0]);
166     // Grant the test user the ability to create tables
167     SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE);
168     verifyAllowed(new AccessTestAction() {
169       @Override
170       public Object run() throws Exception {
171         HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
172         desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
173         HBaseAdmin admin = new HBaseAdmin(conf);
174         try {
175           admin.createTable(desc);
176         } finally {
177           admin.close();
178         }
179         return null;
180       }
181     }, testUser);
182     TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName().getName());
183     // Verify that owner permissions have been granted to the test user on the
184     // table just created
185     List<TablePermission> perms =
186         AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).get(
187           testUser.getShortName());
188     assertNotNull(perms);
189     assertFalse(perms.isEmpty());
190     // Should be RWXCA
191     assertTrue(perms.get(0).implies(Permission.Action.READ));
192     assertTrue(perms.get(0).implies(Permission.Action.WRITE));
193     assertTrue(perms.get(0).implies(Permission.Action.EXEC));
194     assertTrue(perms.get(0).implies(Permission.Action.CREATE));
195     assertTrue(perms.get(0).implies(Permission.Action.ADMIN));
196   }
197 
198   @Test
199   public void testCreateTableWithGroupPermissions() throws Exception {
200     grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.CREATE);
201     try {
202       AccessTestAction createAction = new AccessTestAction() {
203         @Override
204         public Object run() throws Exception {
205           HBaseAdmin admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
206           HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
207           desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
208           try {
209             admin.createTable(desc);
210           } finally {
211             admin.close();
212           }
213           return null;
214         }
215       };
216       verifyAllowed(createAction, TESTGROUP1_USER1);
217       verifyDenied(createAction, TESTGROUP2_USER1);
218     } finally {
219       revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.CREATE);
220     }
221   }
222 
223   @Test
224   public void testACLTableAccess() throws Exception {
225     final Configuration conf = TEST_UTIL.getConfiguration();
226 
227     // Superuser
228     User superUser = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
229 
230     // Global users
231     User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]);
232     User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]);
233     User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]);
234     User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]);
235     SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ);
236     SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE);
237     SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE);
238     SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN);
239 
240     // Namespace users
241     User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]);
242     User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]);
243     User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]);
244     User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]);
245     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsRead.getShortName(),
246       TEST_TABLE.getTableName().getNamespaceAsString(), Action.READ);
247     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsWrite.getShortName(),
248       TEST_TABLE.getTableName().getNamespaceAsString(), Action.WRITE);
249     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsCreate.getShortName(),
250       TEST_TABLE.getTableName().getNamespaceAsString(), Action.CREATE);
251     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsAdmin.getShortName(),
252       TEST_TABLE.getTableName().getNamespaceAsString(), Action.ADMIN);
253 
254     // Table users
255     User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]);
256     User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]);
257     User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]);
258     User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]);
259     SecureTestUtil.grantOnTable(TEST_UTIL, tableRead.getShortName(),
260       TEST_TABLE.getTableName(), null, null, Action.READ);
261     SecureTestUtil.grantOnTable(TEST_UTIL, tableWrite.getShortName(),
262       TEST_TABLE.getTableName(), null, null, Action.WRITE);
263     SecureTestUtil.grantOnTable(TEST_UTIL, tableCreate.getShortName(),
264       TEST_TABLE.getTableName(), null, null, Action.CREATE);
265     SecureTestUtil.grantOnTable(TEST_UTIL, tableAdmin.getShortName(),
266       TEST_TABLE.getTableName(), null, null, Action.ADMIN);
267 
268     grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.WRITE);
269     try {
270       // Write tests
271 
272       AccessTestAction writeAction = new AccessTestAction() {
273         @Override
274         public Object run() throws Exception {
275           HTable t = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
276           try {
277             t.put(new Put(TEST_ROW).add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER,
278               TEST_VALUE));
279             return null;
280           } finally {
281             t.close();
282           }
283         }
284       };
285 
286       // All writes to ACL table denied except for GLOBAL WRITE permission and superuser
287 
288       verifyDenied(writeAction, globalAdmin, globalCreate, globalRead, TESTGROUP2_USER1);
289       verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite);
290       verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite);
291       verifyAllowed(writeAction, superUser, globalWrite, TESTGROUP1_USER1);
292     } finally {
293       revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.WRITE);
294     }
295 
296     grantGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.READ);
297     try {
298       // Read tests
299 
300       AccessTestAction scanAction = new AccessTestAction() {
301         @Override
302         public Object run() throws Exception {
303           HTable t = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
304           try {
305             ResultScanner s = t.getScanner(new Scan());
306             try {
307               for (Result r = s.next(); r != null; r = s.next()) {
308                 // do nothing
309               }
310             } finally {
311               s.close();
312             }
313             return null;
314           } finally {
315             t.close();
316           }
317         }
318       };
319 
320       // All reads from ACL table denied except for GLOBAL READ and superuser
321 
322       verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite, TESTGROUP2_USER1);
323       verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite);
324       verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite);
325       verifyAllowed(scanAction, superUser, globalRead, TESTGROUP1_USER1);
326     } finally {
327       revokeGlobal(TEST_UTIL, TESTGROUP_1_NAME, Action.READ);
328     }
329   }
330 
331   /*
332    * Test table scan operation at table, column family and column qualifier level.
333    */
334   @Test(timeout = 300000)
335   public void testPostGrantAndRevokeScanAction() throws Exception {
336     TableName name = TableName.valueOf(tableName);
337     AccessTestAction scanTableActionForGroupWithTableLevelAccess = new AccessTestAction() {
338       @Override
339       public Void run() throws Exception {
340         HTable table = new HTable(conf, tableName);
341         Scan s1 = new Scan();
342         ResultScanner scanner1 = table.getScanner(s1);
343         try {
344           Result[] next1 = scanner1.next(5);
345           assertTrue("User having table level access should be able to scan all "
346               + "the data in the table.", next1.length == 3);
347         } finally {
348           scanner1.close();
349           table.close();
350         }
351         return null;
352       }
353     };
354 
355     AccessTestAction scanTableActionForGroupWithFamilyLevelAccess = new AccessTestAction() {
356       @Override
357       public Void run() throws Exception {
358         HTable table = new HTable(conf, tableName);
359         Scan s1 = new Scan();
360         ResultScanner scanner1 = table.getScanner(s1);
361         try {
362           Result[] next1 = scanner1.next(5);
363           assertTrue("User having column family level access should be able to scan all "
364               + "the data belonging to that family.", next1.length == 2);
365         } finally {
366           scanner1.close();
367           table.close();
368         }
369         return null;
370       }
371     };
372 
373     AccessTestAction scanFamilyActionForGroupWithFamilyLevelAccess = new AccessTestAction() {
374       @Override
375       public Void run() throws Exception {
376         HTable table = new HTable(conf, tableName);
377         Scan s1 = new Scan();
378         s1.addFamily(TEST_FAMILY_2);
379         ResultScanner scanner1 = null;
380         try {
381           scanner1 = table.getScanner(s1);
382         } finally {
383           if (scanner1 != null) {
384             scanner1.close();
385           }
386           table.close();
387         }
388         return null;
389       }
390     };
391 
392     AccessTestAction scanTableActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
393       @Override
394       public Void run() throws Exception {
395         HTable table = new HTable(conf, tableName);
396         Scan s1 = new Scan();
397         ResultScanner scanner1 = table.getScanner(s1);
398         try {
399           Result[] next1 = scanner1.next(5);
400           assertTrue("User having column qualifier level access should be able to scan "
401               + "that column family qualifier data.", next1.length == 1);
402         } finally {
403           scanner1.close();
404           table.close();
405         }
406         return null;
407       }
408     };
409 
410     AccessTestAction scanFamilyActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
411       @Override
412       public Void run() throws Exception {
413 
414         HTable table = new HTable(conf, tableName);
415         Scan s1 = new Scan();
416         s1.addFamily(TEST_FAMILY_2);
417         ResultScanner scanner1 = null;
418         try {
419           scanner1 = table.getScanner(s1);
420         } finally {
421           if (scanner1 != null) {
422             scanner1.close();
423           }
424           table.close();
425         }
426         return null;
427       }
428     };
429 
430     AccessTestAction scanQualifierActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
431       @Override
432       public Void run() throws Exception {
433         HTable table = new HTable(conf, tableName);
434         Scan s1 = new Scan();
435         s1.addColumn(TEST_FAMILY, Q2);
436         ResultScanner scanner1 = null;
437         try {
438           scanner1 = table.getScanner(s1);
439         } finally {
440           if (scanner1 != null) {
441             scanner1.close();
442           }
443           table.close();
444         }
445         return null;
446       }
447     };
448 
449     // Verify user from a group which has table level access can read all the data and group which
450     // has no access can't read any data.
451     grantOnTable(TEST_UTIL, '@' + TESTGROUP_1, name, null, null, Permission.Action.READ);
452     verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess);
453     verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithTableLevelAccess);
454 
455     // Verify user from a group whose table level access has been revoked can't read any data.
456     revokeFromTable(TEST_UTIL, '@' + TESTGROUP_1, name, null, null);
457     verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess);
458 
459     // Verify user from a group which has column family level access can read all the data
460     // belonging to that family and group which has no access can't read any data.
461     grantOnTable(TEST_UTIL, '@' + TESTGROUP_1, name, TEST_FAMILY, null, Permission.Action.READ);
462     verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess);
463     verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithFamilyLevelAccess);
464     verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithFamilyLevelAccess);
465     verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithFamilyLevelAccess);
466 
467     // Verify user from a group whose column family level access has been revoked can't read any
468     // data from that family.
469     revokeFromTable(TEST_UTIL, '@' + TESTGROUP_1, name, TEST_FAMILY, null);
470     verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess);
471 
472     // Verify user from a group which has column qualifier level access can read data that has this
473     // family and qualifier, and group which has no access can't read any data.
474     grantOnTable(TEST_UTIL, '@' + TESTGROUP_1, name, TEST_FAMILY, Q1, Permission.Action.READ);
475     verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess);
476     verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithQualifierLevelAccess);
477     verifyDenied(TESTGROUP1_USER1, scanQualifierActionForGroupWithQualifierLevelAccess);
478     verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithQualifierLevelAccess);
479     verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithQualifierLevelAccess);
480     verifyDenied(TESTGROUP2_USER1, scanQualifierActionForGroupWithQualifierLevelAccess);
481 
482     // Verify user from a group whose column qualifier level access has been revoked can't read the
483     // data having this column family and qualifier.
484     revokeFromTable(TEST_UTIL, '@' + TESTGROUP_1, name, TEST_FAMILY, Q1);
485     verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess);
486   }
487 
488   public static class MyAccessController extends AccessController {
489   }
490 
491   @Test
492   public void testCoprocessorLoading() throws Exception {
493     MasterCoprocessorHost cpHost =
494         TEST_UTIL.getMiniHBaseCluster().getMaster().getCoprocessorHost();
495     cpHost.load(MyAccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
496     AccessController ACCESS_CONTROLLER = (AccessController) cpHost.findCoprocessor(
497       MyAccessController.class.getName());
498     MasterCoprocessorEnvironment CP_ENV = cpHost.createEnvironment(
499       MyAccessController.class, ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf);
500     RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
501         .getCoprocessorHost();
502     RegionServerCoprocessorEnvironment RSCP_ENV = rsHost.createEnvironment(
503       MyAccessController.class, ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf);
504   }
505 
506   @Test
507   public void testACLZNodeDeletion() throws Exception {
508     String baseAclZNode = "/hbase/acl/";
509     String ns = "testACLZNodeDeletionNamespace";
510     NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build();
511     createNamespace(TEST_UTIL, desc);
512 
513     final TableName table = TableName.valueOf(ns, "testACLZNodeDeletionTable");
514     final byte[] family = Bytes.toBytes("f1");
515     HTableDescriptor htd = new HTableDescriptor(table);
516     htd.addFamily(new HColumnDescriptor(family));
517     TEST_UTIL.getHBaseAdmin().createTable(htd);
518 
519     // Namespace needs this, as they follow the lazy creation of ACL znode.
520     grantOnNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN);
521     ZooKeeperWatcher zkw = TEST_UTIL.getMiniHBaseCluster().getMaster().getZooKeeper();
522     assertTrue("The acl znode for table should exist",  ZKUtil.checkExists(zkw, baseAclZNode +
523         table.getNameAsString()) != -1);
524     assertTrue("The acl znode for namespace should exist", ZKUtil.checkExists(zkw, baseAclZNode +
525         convertToNamespace(ns)) != -1);
526 
527     revokeFromNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN);
528     TEST_UTIL.deleteTable(table);
529     deleteNamespace(TEST_UTIL, ns);
530 
531     assertTrue("The acl znode for table should have been deleted",
532         ZKUtil.checkExists(zkw, baseAclZNode + table.getNameAsString()) == -1);
533     assertTrue( "The acl znode for namespace should have been deleted",
534         ZKUtil.checkExists(zkw, baseAclZNode + convertToNamespace(ns)) == -1);
535   }
536 }