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.AuthUtil.toGroupEntry;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertTrue;
023
024import java.util.Arrays;
025import java.util.List;
026import java.util.Map;
027import java.util.Objects;
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.HBaseTestingUtil;
031import org.apache.hadoop.hbase.HConstants;
032import org.apache.hadoop.hbase.NamespaceDescriptor;
033import org.apache.hadoop.hbase.TableName;
034import org.apache.hadoop.hbase.client.Admin;
035import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
036import org.apache.hadoop.hbase.client.Connection;
037import org.apache.hadoop.hbase.client.ConnectionFactory;
038import org.apache.hadoop.hbase.client.Get;
039import org.apache.hadoop.hbase.client.Result;
040import org.apache.hadoop.hbase.client.Table;
041import org.apache.hadoop.hbase.client.TableDescriptor;
042import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
043import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
044import org.apache.hadoop.hbase.coprocessor.ObserverContextImpl;
045import org.apache.hadoop.hbase.ipc.NettyRpcClientConfigHelper;
046import org.apache.hadoop.hbase.security.User;
047import org.apache.hadoop.hbase.security.access.Permission.Action;
048import org.apache.hadoop.hbase.testclassification.MediumTests;
049import org.apache.hadoop.hbase.testclassification.SecurityTests;
050import org.apache.hadoop.hbase.util.Bytes;
051import org.apache.hadoop.hbase.util.JVMClusterUtil;
052import org.junit.AfterClass;
053import org.junit.BeforeClass;
054import org.junit.ClassRule;
055import org.junit.Test;
056import org.junit.experimental.categories.Category;
057import org.slf4j.Logger;
058import org.slf4j.LoggerFactory;
059
060import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap;
061import org.apache.hbase.thirdparty.com.google.protobuf.BlockingRpcChannel;
062
063import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.AccessControlService;
064
065@Category({ SecurityTests.class, MediumTests.class })
066public class TestNamespaceCommands extends SecureTestUtil {
067
068  @ClassRule
069  public static final HBaseClassTestRule CLASS_RULE =
070    HBaseClassTestRule.forClass(TestNamespaceCommands.class);
071
072  private static HBaseTestingUtil UTIL = new HBaseTestingUtil();
073  private static final Logger LOG = LoggerFactory.getLogger(TestNamespaceCommands.class);
074  private static String TEST_NAMESPACE = "ns1";
075  private static String TEST_NAMESPACE2 = "ns2";
076  private static Configuration conf;
077  private static MasterCoprocessorEnvironment CP_ENV;
078  private static AccessController ACCESS_CONTROLLER;
079
080  // user with all permissions
081  private static User SUPERUSER;
082
083  // user with A permission on global
084  private static User USER_GLOBAL_ADMIN;
085  // user with C permission on global
086  private static User USER_GLOBAL_CREATE;
087  // user with W permission on global
088  private static User USER_GLOBAL_WRITE;
089  // user with R permission on global
090  private static User USER_GLOBAL_READ;
091  // user with X permission on global
092  private static User USER_GLOBAL_EXEC;
093
094  // user with A permission on namespace
095  private static User USER_NS_ADMIN;
096  // user with C permission on namespace
097  private static User USER_NS_CREATE;
098  // user with W permission on namespace
099  private static User USER_NS_WRITE;
100  // user with R permission on namespace.
101  private static User USER_NS_READ;
102  // user with X permission on namespace.
103  private static User USER_NS_EXEC;
104
105  // user with rw permissions
106  private static User USER_TABLE_WRITE; // TODO: WE DO NOT GIVE ANY PERMS TO THIS USER
107  // user with create table permissions alone
108  private static User USER_TABLE_CREATE; // TODO: WE DO NOT GIVE ANY PERMS TO THIS USER
109
110  private static final String GROUP_ADMIN = "group_admin";
111  private static final String GROUP_NS_ADMIN = "group_ns_admin";
112  private static final String GROUP_CREATE = "group_create";
113  private static final String GROUP_READ = "group_read";
114  private static final String GROUP_WRITE = "group_write";
115
116  private static User USER_GROUP_ADMIN;
117  private static User USER_GROUP_NS_ADMIN;
118  private static User USER_GROUP_CREATE;
119  private static User USER_GROUP_READ;
120  private static User USER_GROUP_WRITE;
121
122  private static String TEST_TABLE = TEST_NAMESPACE + ":testtable";
123  private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
124
125  @BeforeClass
126  public static void beforeClass() throws Exception {
127    conf = UTIL.getConfiguration();
128    enableSecurity(conf);
129
130    SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
131    // Users with global permissions
132    USER_GLOBAL_ADMIN = User.createUserForTesting(conf, "global_admin", new String[0]);
133    USER_GLOBAL_CREATE = User.createUserForTesting(conf, "global_create", new String[0]);
134    USER_GLOBAL_WRITE = User.createUserForTesting(conf, "global_write", new String[0]);
135    USER_GLOBAL_READ = User.createUserForTesting(conf, "global_read", new String[0]);
136    USER_GLOBAL_EXEC = User.createUserForTesting(conf, "global_exec", new String[0]);
137
138    USER_NS_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
139    USER_NS_CREATE = User.createUserForTesting(conf, "namespace_create", new String[0]);
140    USER_NS_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
141    USER_NS_READ = User.createUserForTesting(conf, "namespace_read", new String[0]);
142    USER_NS_EXEC = User.createUserForTesting(conf, "namespace_exec", new String[0]);
143
144    USER_TABLE_CREATE = User.createUserForTesting(conf, "table_create", new String[0]);
145    USER_TABLE_WRITE = User.createUserForTesting(conf, "table_write", new String[0]);
146
147    USER_GROUP_ADMIN =
148      User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN });
149    USER_GROUP_NS_ADMIN =
150      User.createUserForTesting(conf, "user_group_ns_admin", new String[] { GROUP_NS_ADMIN });
151    USER_GROUP_CREATE =
152      User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE });
153    USER_GROUP_READ =
154      User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ });
155    USER_GROUP_WRITE =
156      User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE });
157    // TODO: other table perms
158
159    UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 2);
160    UTIL.startMiniCluster();
161    // Wait for the ACL table to become available
162    UTIL.waitTableAvailable(PermissionStorage.ACL_TABLE_NAME.getName(), 30 * 1000);
163
164    // Find the Access Controller CP. Could be on master or if master is not serving regions, is
165    // on an arbitrary server.
166    for (JVMClusterUtil.RegionServerThread rst : UTIL.getMiniHBaseCluster()
167      .getLiveRegionServerThreads()) {
168      ACCESS_CONTROLLER = rst.getRegionServer().getRegionServerCoprocessorHost()
169        .findCoprocessor(AccessController.class);
170      if (ACCESS_CONTROLLER != null) {
171        break;
172      }
173    }
174    if (ACCESS_CONTROLLER == null) {
175      throw new NullPointerException();
176    }
177
178    UTIL.getAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build());
179    UTIL.getAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build());
180
181    // grants on global
182    grantGlobal(UTIL, USER_GLOBAL_ADMIN.getShortName(), Permission.Action.ADMIN);
183    grantGlobal(UTIL, USER_GLOBAL_CREATE.getShortName(), Permission.Action.CREATE);
184    grantGlobal(UTIL, USER_GLOBAL_WRITE.getShortName(), Permission.Action.WRITE);
185    grantGlobal(UTIL, USER_GLOBAL_READ.getShortName(), Permission.Action.READ);
186    grantGlobal(UTIL, USER_GLOBAL_EXEC.getShortName(), Permission.Action.EXEC);
187
188    // grants on namespace
189    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN);
190    grantOnNamespace(UTIL, USER_NS_CREATE.getShortName(), TEST_NAMESPACE, Permission.Action.CREATE);
191    grantOnNamespace(UTIL, USER_NS_WRITE.getShortName(), TEST_NAMESPACE, Permission.Action.WRITE);
192    grantOnNamespace(UTIL, USER_NS_READ.getShortName(), TEST_NAMESPACE, Permission.Action.READ);
193    grantOnNamespace(UTIL, USER_NS_EXEC.getShortName(), TEST_NAMESPACE, Permission.Action.EXEC);
194    grantOnNamespace(UTIL, toGroupEntry(GROUP_NS_ADMIN), TEST_NAMESPACE, Permission.Action.ADMIN);
195
196    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN);
197
198    grantGlobal(UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN);
199    grantGlobal(UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE);
200    grantGlobal(UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ);
201    grantGlobal(UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE);
202  }
203
204  @AfterClass
205  public static void afterClass() throws Exception {
206    UTIL.getAdmin().deleteNamespace(TEST_NAMESPACE);
207    UTIL.getAdmin().deleteNamespace(TEST_NAMESPACE2);
208    UTIL.shutdownMiniCluster();
209  }
210
211  @Test
212  public void testAclTableEntries() throws Exception {
213    String userTestNamespace = "userTestNsp";
214    Table acl = UTIL.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME);
215    try {
216      ListMultimap<String, UserPermission> perms =
217        PermissionStorage.getNamespacePermissions(conf, TEST_NAMESPACE);
218      for (Map.Entry<String, UserPermission> entry : perms.entries()) {
219        LOG.debug(Objects.toString(entry));
220      }
221      assertEquals(6, perms.size());
222
223      // Grant and check state in ACL table
224      grantOnNamespace(UTIL, userTestNamespace, TEST_NAMESPACE, Permission.Action.WRITE);
225
226      Result result = acl.get(new Get(Bytes.toBytes(userTestNamespace)));
227      assertTrue(result != null);
228      perms = PermissionStorage.getNamespacePermissions(conf, TEST_NAMESPACE);
229      assertEquals(7, perms.size());
230      List<UserPermission> namespacePerms = perms.get(userTestNamespace);
231      assertTrue(perms.containsKey(userTestNamespace));
232      assertEquals(1, namespacePerms.size());
233      assertEquals(TEST_NAMESPACE,
234        ((NamespacePermission) namespacePerms.get(0).getPermission()).getNamespace());
235      assertEquals(1, namespacePerms.get(0).getPermission().getActions().length);
236      assertEquals(Permission.Action.WRITE, namespacePerms.get(0).getPermission().getActions()[0]);
237
238      // Revoke and check state in ACL table
239      revokeFromNamespace(UTIL, userTestNamespace, TEST_NAMESPACE, Permission.Action.WRITE);
240
241      perms = PermissionStorage.getNamespacePermissions(conf, TEST_NAMESPACE);
242      assertEquals(6, perms.size());
243    } finally {
244      acl.close();
245    }
246  }
247
248  @Test
249  public void testModifyNamespace() throws Exception {
250    AccessTestAction modifyNamespace = new AccessTestAction() {
251      @Override
252      public Object run() throws Exception {
253        ACCESS_CONTROLLER.preModifyNamespace(ObserverContextImpl.createAndPrepare(CP_ENV), null, // not
254                                                                                                 // needed
255                                                                                                 // by
256                                                                                                 // AccessController
257          NamespaceDescriptor.create(TEST_NAMESPACE).addConfiguration("abc", "156").build());
258        return null;
259      }
260    };
261
262    // modifyNamespace: superuser | global(A) | NS(A)
263    verifyAllowed(modifyNamespace, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN);
264    verifyDenied(modifyNamespace, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
265      USER_GLOBAL_EXEC, USER_NS_ADMIN, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
266      USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
267  }
268
269  @Test
270  public void testCreateAndDeleteNamespace() throws Exception {
271    AccessTestAction createNamespace = new AccessTestAction() {
272      @Override
273      public Object run() throws Exception {
274        ACCESS_CONTROLLER.preCreateNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
275          NamespaceDescriptor.create(TEST_NAMESPACE2).build());
276        return null;
277      }
278    };
279
280    AccessTestAction deleteNamespace = new AccessTestAction() {
281      @Override
282      public Object run() throws Exception {
283        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContextImpl.createAndPrepare(CP_ENV),
284          TEST_NAMESPACE2);
285        return null;
286      }
287    };
288
289    // createNamespace: superuser | global(A)
290    verifyAllowed(createNamespace, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN);
291    // all others should be denied
292    verifyDenied(createNamespace, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
293      USER_GLOBAL_EXEC, USER_NS_ADMIN, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
294      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
295
296    // deleteNamespace: superuser | global(A) | NS(A)
297    verifyAllowed(deleteNamespace, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN);
298    verifyDenied(deleteNamespace, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
299      USER_GLOBAL_EXEC, USER_NS_ADMIN, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
300      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
301  }
302
303  @Test
304  public void testGetNamespaceDescriptor() throws Exception {
305    AccessTestAction getNamespaceAction = new AccessTestAction() {
306      @Override
307      public Object run() throws Exception {
308        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContextImpl.createAndPrepare(CP_ENV),
309          TEST_NAMESPACE);
310        return null;
311      }
312    };
313    // getNamespaceDescriptor : superuser | global(A) | NS(A)
314    verifyAllowed(getNamespaceAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_NS_ADMIN,
315      USER_GROUP_ADMIN);
316    verifyDenied(getNamespaceAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
317      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
318      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
319  }
320
321  @Test
322  public void testListNamespaces() throws Exception {
323    AccessTestAction listAction = new AccessTestAction() {
324      @Override
325      public Object run() throws Exception {
326        Connection unmanagedConnection =
327          ConnectionFactory.createConnection(UTIL.getConfiguration());
328        Admin admin = unmanagedConnection.getAdmin();
329        try {
330          return Arrays.asList(admin.listNamespaceDescriptors());
331        } finally {
332          admin.close();
333          unmanagedConnection.close();
334        }
335      }
336    };
337
338    // listNamespaces : All access*
339    // * Returned list will only show what you can call getNamespaceDescriptor()
340
341    verifyAllowed(listAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_NS_ADMIN, USER_GROUP_ADMIN);
342
343    // we have 3 namespaces: [default, hbase, TEST_NAMESPACE, TEST_NAMESPACE2]
344    assertEquals(4, ((List) SUPERUSER.runAs(listAction)).size());
345    assertEquals(4, ((List) USER_GLOBAL_ADMIN.runAs(listAction)).size());
346    assertEquals(4, ((List) USER_GROUP_ADMIN.runAs(listAction)).size());
347
348    assertEquals(2, ((List) USER_NS_ADMIN.runAs(listAction)).size());
349
350    assertEquals(0, ((List) USER_GLOBAL_CREATE.runAs(listAction)).size());
351    assertEquals(0, ((List) USER_GLOBAL_WRITE.runAs(listAction)).size());
352    assertEquals(0, ((List) USER_GLOBAL_READ.runAs(listAction)).size());
353    assertEquals(0, ((List) USER_GLOBAL_EXEC.runAs(listAction)).size());
354    assertEquals(0, ((List) USER_NS_CREATE.runAs(listAction)).size());
355    assertEquals(0, ((List) USER_NS_WRITE.runAs(listAction)).size());
356    assertEquals(0, ((List) USER_NS_READ.runAs(listAction)).size());
357    assertEquals(0, ((List) USER_NS_EXEC.runAs(listAction)).size());
358    assertEquals(0, ((List) USER_TABLE_CREATE.runAs(listAction)).size());
359    assertEquals(0, ((List) USER_TABLE_WRITE.runAs(listAction)).size());
360    assertEquals(0, ((List) USER_GROUP_CREATE.runAs(listAction)).size());
361    assertEquals(0, ((List) USER_GROUP_READ.runAs(listAction)).size());
362    assertEquals(0, ((List) USER_GROUP_WRITE.runAs(listAction)).size());
363  }
364
365  @SuppressWarnings("checkstyle:MethodLength")
366  @Test
367  public void testGrantRevoke() throws Exception {
368    final String testUser = "testUser";
369    // Set this else in test context, with limit on the number of threads for
370    // netty eventloopgroup, we can run out of threads if one group used throughout.
371    NettyRpcClientConfigHelper.createEventLoopPerClient(conf);
372    // Test if client API actions are authorized
373    AccessTestAction grantAction = new AccessTestAction() {
374      @Override
375      public Object run() throws Exception {
376        try (Connection connection = ConnectionFactory.createConnection(conf)) {
377          connection.getAdmin().grant(new UserPermission(testUser,
378            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()), false);
379        }
380        return null;
381      }
382    };
383    AccessTestAction grantNamespaceAction = new AccessTestAction() {
384      @Override
385      public Object run() throws Exception {
386        try (Connection conn = ConnectionFactory.createConnection(conf)) {
387          conn.getAdmin().grant(new UserPermission(USER_GROUP_NS_ADMIN.getShortName(),
388            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.READ).build()), false);
389        }
390        return null;
391      }
392    };
393
394    AccessTestAction revokeAction = new AccessTestAction() {
395      @Override
396      public Object run() throws Exception {
397        try (Connection connection = ConnectionFactory.createConnection(conf)) {
398          connection.getAdmin().revoke(new UserPermission(testUser,
399            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()));
400        }
401        return null;
402      }
403    };
404    AccessTestAction revokeNamespaceAction = new AccessTestAction() {
405      @Override
406      public Object run() throws Exception {
407        try (Connection connection = ConnectionFactory.createConnection(conf)) {
408          connection.getAdmin().revoke(new UserPermission(USER_GROUP_NS_ADMIN.getShortName(),
409            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.READ).build()));
410        }
411        return null;
412      }
413    };
414
415    AccessTestAction getPermissionsAction = new AccessTestAction() {
416      @Override
417      public Object run() throws Exception {
418        try (Connection connection = ConnectionFactory.createConnection(conf)) {
419          connection.getAdmin()
420            .getUserPermissions(GetUserPermissionsRequest.newBuilder(TEST_NAMESPACE).build());
421        }
422        return null;
423      }
424    };
425
426    AccessTestAction preGrantAction = new AccessTestAction() {
427      @Override
428      public Object run() throws Exception {
429        ACCESS_CONTROLLER.preGrant(ObserverContextImpl.createAndPrepare(CP_ENV),
430          new UserPermission(testUser,
431            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()),
432          false);
433        return null;
434      }
435    };
436    AccessTestAction preRevokeAction = new AccessTestAction() {
437      @Override
438      public Object run() throws Exception {
439        ACCESS_CONTROLLER.preRevoke(ObserverContextImpl.createAndPrepare(CP_ENV),
440          new UserPermission(testUser,
441            Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()));
442        return null;
443      }
444    };
445
446    AccessTestAction grantCPAction = new AccessTestAction() {
447      @Override
448      public Object run() throws Exception {
449        try (Connection connection = ConnectionFactory.createConnection(conf);
450          Table acl = connection.getTable(PermissionStorage.ACL_TABLE_NAME)) {
451          BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
452          AccessControlService.BlockingInterface protocol =
453            AccessControlService.newBlockingStub(service);
454          AccessControlUtil.grant(null, protocol, testUser, TEST_NAMESPACE, false, Action.WRITE);
455        }
456        return null;
457      }
458    };
459    AccessTestAction revokeCPAction = new AccessTestAction() {
460      @Override
461      public Object run() throws Exception {
462        try (Connection connection = ConnectionFactory.createConnection(conf);
463          Table acl = connection.getTable(PermissionStorage.ACL_TABLE_NAME)) {
464          BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
465          AccessControlService.BlockingInterface protocol =
466            AccessControlService.newBlockingStub(service);
467          AccessControlUtil.revoke(null, protocol, testUser, TEST_NAMESPACE, Action.WRITE);
468        }
469        return null;
470      }
471    };
472
473    verifyAllowed(grantAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
474    verifyDenied(grantAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
475      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
476      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
477    verifyAllowed(grantNamespaceAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN,
478      USER_NS_ADMIN, USER_GROUP_NS_ADMIN);
479    verifyDenied(grantNamespaceAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
480      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
481      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
482
483    verifyAllowed(revokeAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
484    verifyDenied(revokeAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
485      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
486      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
487    verifyAllowed(revokeNamespaceAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN,
488      USER_NS_ADMIN, USER_GROUP_NS_ADMIN);
489    verifyDenied(revokeNamespaceAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
490      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
491      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
492
493    verifyAllowed(getPermissionsAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_NS_ADMIN,
494      USER_GROUP_ADMIN);
495    verifyDenied(getPermissionsAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
496      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
497      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
498
499    verifyAllowed(preGrantAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
500    verifyDenied(preGrantAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
501      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
502      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
503    verifyAllowed(preRevokeAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
504    verifyDenied(preRevokeAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
505      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
506      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
507
508    verifyAllowed(grantCPAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
509    verifyDenied(grantCPAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
510      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
511      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
512    verifyAllowed(revokeCPAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN);
513    verifyDenied(revokeCPAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ,
514      USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC,
515      USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
516  }
517
518  @Test
519  public void testCreateTableWithNamespace() throws Exception {
520    AccessTestAction createTable = new AccessTestAction() {
521      @Override
522      public Object run() throws Exception {
523        TableDescriptor tableDescriptor =
524          TableDescriptorBuilder.newBuilder(TableName.valueOf(TEST_TABLE))
525            .setColumnFamily(ColumnFamilyDescriptorBuilder.of(TEST_FAMILY)).build();
526        ACCESS_CONTROLLER.preCreateTable(ObserverContextImpl.createAndPrepare(CP_ENV),
527          tableDescriptor, null);
528        return null;
529      }
530    };
531
532    // createTable : superuser | global(AC) | NS(AC)
533    verifyAllowed(createTable, SUPERUSER, USER_GLOBAL_CREATE, USER_NS_CREATE, USER_GROUP_CREATE,
534      USER_GLOBAL_ADMIN, USER_NS_ADMIN, USER_GROUP_ADMIN);
535    verifyDenied(createTable, USER_GLOBAL_WRITE, USER_GLOBAL_READ, USER_GLOBAL_EXEC, USER_NS_WRITE,
536      USER_NS_READ, USER_NS_EXEC, USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ,
537      USER_GROUP_WRITE);
538  }
539}