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