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