public boolean matchPermission(
      User user, byte[] table, byte[] family, byte[] qualifier, TablePermission.Action action) {
    PermissionCache<TablePermission> tablePerms = tableCache.get(table);
    if (tablePerms != null) {
      List<TablePermission> userPerms = tablePerms.getUser(user.getShortName());
      if (userPerms != null) {
        for (TablePermission p : userPerms) {
          if (p.matchesFamilyQualifier(table, family, qualifier, action)) {
            return true;
          }
        }
      }

      String[] groups = user.getGroupNames();
      if (groups != null) {
        for (String group : groups) {
          List<TablePermission> groupPerms = tablePerms.getGroup(group);
          if (groupPerms != null) {
            for (TablePermission p : groupPerms) {
              if (p.matchesFamilyQualifier(table, family, qualifier, action)) {
                return true;
              }
            }
          }
        }
      }
    }

    return false;
  }
  /**
   * Returns a new {@code PermissionCache} initialized with permission assignments from the {@code
   * hbase.superuser} configuration key.
   */
  private PermissionCache<Permission> initGlobal(Configuration conf) throws IOException {
    UserProvider userProvider = UserProvider.instantiate(conf);
    User user = userProvider.getCurrent();
    if (user == null) {
      throw new IOException(
          "Unable to obtain the current user, "
              + "authorization checks for internal operations will not work correctly!");
    }
    PermissionCache<Permission> newCache = new PermissionCache<Permission>();
    String currentUser = user.getShortName();

    // the system user is always included
    List<String> superusers =
        Lists.asList(
            currentUser, conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0]));
    if (superusers != null) {
      for (String name : superusers) {
        if (AccessControlLists.isGroupPrincipal(name)) {
          newCache.putGroup(
              AccessControlLists.getGroupName(name), new Permission(Permission.Action.values()));
        } else {
          newCache.putUser(name, new Permission(Permission.Action.values()));
        }
      }
    }
    return newCache;
  }
  private User getActiveUser() {
    User user = RequestContext.getRequestUser();
    if (!RequestContext.isInRequestContext()) {
      return null;
    }

    // this is for testing
    if (userProvider.isHadoopSecurityEnabled()
        && "simple".equalsIgnoreCase(conf.get(User.HBASE_SECURITY_CONF_KEY))) {
      return User.createUserForTesting(conf, user.getShortName(), new String[] {});
    }

    return user;
  }
  public boolean authorize(
      User user, byte[] table, byte[] family, byte[] qualifier, Permission.Action action) {
    if (authorizeUser(user.getShortName(), table, family, qualifier, action)) {
      return true;
    }

    String[] groups = user.getGroupNames();
    if (groups != null) {
      for (String group : groups) {
        if (authorizeGroup(group, table, family, action)) {
          return true;
        }
      }
    }
    return false;
  }
Beispiel #5
0
 @Override // simply use the default Object#hashcode() ?
 public int hashCode() {
   return (address.hashCode()
           + PRIME
               * (PRIME * System.identityHashCode(protocol)
                   ^ (ticket == null ? 0 : ticket.hashCode())))
       ^ rpcTimeout;
 }
Beispiel #6
0
 @Override
 public boolean rollback(final Server server, final RegionServerServices services)
     throws IOException {
   if (User.isHBaseSecurityEnabled(parent.getBaseConf())) {
     LOG.warn("Should use rollback(Server, RegionServerServices, User)");
   }
   return rollback(server, services, null);
 }
Beispiel #7
0
 @Override
 public PairOfSameType<Region> execute(final Server server, final RegionServerServices services)
     throws IOException {
   if (User.isHBaseSecurityEnabled(parent.getBaseConf())) {
     LOG.warn("Should use execute(Server, RegionServerServices, User)");
   }
   return execute(server, services, null);
 }
Beispiel #8
0
 @Override
 public void whoAmI(
     RpcController controller,
     AuthenticationProtos.WhoAmIRequest request,
     RpcCallback<AuthenticationProtos.WhoAmIResponse> done) {
   User requestUser = RequestContext.getRequestUser();
   AuthenticationProtos.WhoAmIResponse.Builder response =
       AuthenticationProtos.WhoAmIResponse.newBuilder();
   if (requestUser != null) {
     response.setUsername(requestUser.getShortName());
     AuthenticationMethod method = requestUser.getUGI().getAuthenticationMethod();
     if (method != null) {
       response.setAuthMethod(method.name());
     }
   }
   done.run(response.build());
 }
Beispiel #9
0
    Connection(ConnectionId remoteId) throws IOException {
      if (remoteId.getAddress().isUnresolved()) {
        throw new UnknownHostException("unknown host: " + remoteId.getAddress().getHostName());
      }
      this.remoteId = remoteId;
      User ticket = remoteId.getTicket();
      Class<? extends VersionedProtocol> protocol = remoteId.getProtocol();

      header = new ConnectionHeader(protocol == null ? null : protocol.getName(), ticket);

      this.setName(
          "IPC Client ("
              + socketFactory.hashCode()
              + ") connection to "
              + remoteId.getAddress().toString()
              + ((ticket == null) ? " from an unknown user" : (" from " + ticket.getName())));
      this.setDaemon(true);
    }
  @BeforeClass
  public static void setupBeforeClass() throws Exception {
    conf = TEST_UTIL.getConfiguration();
    // Enable security
    enableSecurity(conf);
    // Verify enableSecurity sets up what we require
    verifyConfiguration(conf);
    TEST_UTIL.startMiniCluster();
    // Wait for the ACL table to become available
    TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);

    TESTGROUP1_USER1 =
        User.createUserForTesting(conf, "testgroup1_user1", new String[] {TESTGROUP_1});
    TESTGROUP2_USER1 =
        User.createUserForTesting(conf, "testgroup2_user2", new String[] {TESTGROUP_2});

    connection = ConnectionFactory.createConnection(conf);
  }
 public JVMClusterUtil.MasterThread addMaster(final Configuration c, final int index, User user)
     throws IOException, InterruptedException {
   return user.runAs(
       new PrivilegedExceptionAction<JVMClusterUtil.MasterThread>() {
         public JVMClusterUtil.MasterThread run() throws Exception {
           return addMaster(c, index);
         }
       });
 }
Beispiel #12
0
  /**
   * Authorize a global permission based on ACLs for the given user and the user's groups.
   *
   * @param user
   * @param action
   * @return
   */
  public boolean authorize(User user, Permission.Action action) {
    if (user == null) {
      return false;
    }

    if (authorize(globalCache.getUser(user.getShortName()), action)) {
      return true;
    }

    String[] groups = user.getGroupNames();
    if (groups != null) {
      for (String group : groups) {
        if (authorize(globalCache.getGroup(group), action)) {
          return true;
        }
      }
    }
    return false;
  }
 private Path createStagingDir(Path baseDir, User user, TableName tableName) throws IOException {
   String tblName = tableName.getNameAsString().replace(":", "_");
   String randomDir =
       user.getShortName()
           + "__"
           + tblName
           + "__"
           + (new BigInteger(RANDOM_WIDTH, random).toString(RANDOM_RADIX));
   return createStagingDir(baseDir, user, randomDir);
 }
Beispiel #14
0
 @Override
 public boolean equals(Object obj) {
   if (obj instanceof ConnectionId) {
     ConnectionId id = (ConnectionId) obj;
     return address.equals(id.address)
         && protocol == id.protocol
         && ((ticket != null && ticket.equals(id.ticket)) || (ticket == id.ticket))
         && rpcTimeout == id.rpcTimeout;
   }
   return false;
 }
Beispiel #15
0
  public boolean authorize(User user, byte[] table, KeyValue kv, TablePermission.Action action) {
    PermissionCache<TablePermission> tablePerms = tableCache.get(table);
    if (tablePerms != null) {
      List<TablePermission> userPerms = tablePerms.getUser(user.getShortName());
      if (authorize(userPerms, table, kv, action)) {
        return true;
      }

      String[] groupNames = user.getGroupNames();
      if (groupNames != null) {
        for (String group : groupNames) {
          List<TablePermission> groupPerms = tablePerms.getGroup(group);
          if (authorize(groupPerms, table, kv, action)) {
            return true;
          }
        }
      }
    }

    return false;
  }
 @Test
 public void testCreateWithCorrectOwner() throws Exception {
   // Create a test user
   final User testUser =
       User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser", new String[0]);
   // Grant the test user the ability to create tables
   SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE);
   verifyAllowed(
       new AccessTestAction() {
         @Override
         public Object run() throws Exception {
           HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
           desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
           try (Connection connection =
               ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) {
             try (Admin admin = connection.getAdmin()) {
               admin.createTable(desc);
             }
           }
           return null;
         }
       },
       testUser);
   TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName());
   // Verify that owner permissions have been granted to the test user on the
   // table just created
   List<TablePermission> perms =
       AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName())
           .get(testUser.getShortName());
   assertNotNull(perms);
   assertFalse(perms.isEmpty());
   // Should be RWXCA
   assertTrue(perms.get(0).implies(Permission.Action.READ));
   assertTrue(perms.get(0).implies(Permission.Action.WRITE));
   assertTrue(perms.get(0).implies(Permission.Action.EXEC));
   assertTrue(perms.get(0).implies(Permission.Action.CREATE));
   assertTrue(perms.get(0).implies(Permission.Action.ADMIN));
 }
Beispiel #17
0
  @Override
  public void getAuthenticationToken(
      RpcController controller,
      AuthenticationProtos.GetAuthenticationTokenRequest request,
      RpcCallback<AuthenticationProtos.GetAuthenticationTokenResponse> done) {
    AuthenticationProtos.GetAuthenticationTokenResponse.Builder response =
        AuthenticationProtos.GetAuthenticationTokenResponse.newBuilder();

    try {
      if (secretManager == null) {
        throw new IOException("No secret manager configured for token authentication");
      }

      User currentUser = RequestContext.getRequestUser();
      UserGroupInformation ugi = null;
      if (currentUser != null) {
        ugi = currentUser.getUGI();
      }
      if (currentUser == null) {
        throw new AccessDeniedException("No authenticated user for request!");
      } else if (!isAllowedDelegationTokenOp(ugi)) {
        LOG.warn(
            "Token generation denied for user="******", authMethod="
                + ugi.getAuthenticationMethod());
        throw new AccessDeniedException(
            "Token generation only allowed for Kerberos authenticated clients");
      }

      Token<AuthenticationTokenIdentifier> token =
          secretManager.generateToken(currentUser.getName());
      response.setToken(ProtobufUtil.toToken(token)).build();
    } catch (IOException ioe) {
      ResponseConverter.setControllerException(controller, ioe);
    }
    done.run(response.build());
  }
  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
    conf = TEST_UTIL.getConfiguration();

    // Set up superuser
    SecureTestUtil.configureSuperuser(conf);

    // Install the VisibilityController as a system processor
    VisibilityTestUtil.enableVisiblityLabels(conf);

    // Now, DISABLE active authorization
    conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);

    TEST_UTIL.startMiniCluster();

    // Wait for the labels table to become available
    TEST_UTIL.waitUntilAllRegionsAssigned(LABELS_TABLE_NAME);

    // create a set of test users
    SUPERUSER = User.createUserForTesting(conf, "admin", new String[] {"supergroup"});
    USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);

    // Define test labels
    SUPERUSER.runAs(
        new PrivilegedExceptionAction<Void>() {
          public Void run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf)) {
              VisibilityClient.addLabels(conn, new String[] {SECRET, CONFIDENTIAL, PRIVATE});
              VisibilityClient.setAuths(
                  conn, new String[] {SECRET, CONFIDENTIAL}, USER_RW.getShortName());
            } catch (Throwable t) {
              fail("Should not have failed");
            }
            return null;
          }
        });
  }
Beispiel #19
0
  @BeforeClass
  public static void setUpOnce() throws Exception {
    miniCluster = System.getProperty("cluster.type").equals("mini");
    securedCluster = System.getProperty("cluster.secured").equals("true");
    System.out.println("realCluster - " + !miniCluster);
    System.out.println("securedCluster - " + securedCluster);

    Util.setLoggingThreshold("ERROR");

    if (miniCluster) {
      if (hbase == null) {
        hbase = new HBaseTestingUtility();
        conf = hbase.getConfiguration();
        conf.set("zookeeper.session.timeout", "3600000");
        conf.set("dfs.client.socket-timeout", "3600000");

        if (securedCluster) {
          hbase.startMiniCluster(RS_COUNT);
          hbase.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME, 30000L);
          admin = new HBaseAdminWrapper(conf);
        } else {
          hbase.startMiniCluster(RS_COUNT);
          admin = hbase.getHBaseAdmin();
        }
      }
    } else {
      if (admin == null) {
        final String argsFileName =
            securedCluster
                ? "../../testClusterRealSecured.args"
                : "../../testClusterRealNonSecured.args";
        if (!Util.isFile(argsFileName)) {
          throw new IllegalStateException(
              "You have to define args file " + argsFileName + " for tests.");
        }

        String[] testArgs = {argsFileName};
        Args args = new TestArgs(testArgs);
        admin = HBaseClient.getAdmin(args);
        conf = admin.getConfiguration();
        RS_COUNT = getServerNameList().size();
      }
    }
    previousBalancerRunning = admin.setBalancerRunning(false, true);
    hConnection = HConnectionManager.createConnection(conf);

    USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
  }
Beispiel #20
0
  @Test
  public void testListNamespaces() throws Exception {
    AccessTestAction listAction =
        new AccessTestAction() {
          @Override
          public Object run() throws Exception {
            Connection unmanagedConnection =
                ConnectionFactory.createConnection(UTIL.getConfiguration());
            Admin admin = unmanagedConnection.getAdmin();
            try {
              return Arrays.asList(admin.listNamespaceDescriptors());
            } finally {
              admin.close();
              unmanagedConnection.close();
            }
          }
        };

    // listNamespaces         : All access*
    // * Returned list will only show what you can call getNamespaceDescriptor()

    verifyAllowed(listAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_NS_ADMIN, USER_GROUP_ADMIN);

    // we have 3 namespaces: [default, hbase, TEST_NAMESPACE, TEST_NAMESPACE2]
    assertEquals(4, ((List) SUPERUSER.runAs(listAction)).size());
    assertEquals(4, ((List) USER_GLOBAL_ADMIN.runAs(listAction)).size());
    assertEquals(4, ((List) USER_GROUP_ADMIN.runAs(listAction)).size());

    assertEquals(2, ((List) USER_NS_ADMIN.runAs(listAction)).size());

    assertEquals(0, ((List) USER_GLOBAL_CREATE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GLOBAL_WRITE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GLOBAL_READ.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GLOBAL_EXEC.runAs(listAction)).size());
    assertEquals(0, ((List) USER_NS_CREATE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_NS_WRITE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_NS_READ.runAs(listAction)).size());
    assertEquals(0, ((List) USER_NS_EXEC.runAs(listAction)).size());
    assertEquals(0, ((List) USER_TABLE_CREATE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_TABLE_WRITE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GROUP_CREATE.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GROUP_READ.runAs(listAction)).size());
    assertEquals(0, ((List) USER_GROUP_WRITE.runAs(listAction)).size());
  }
Beispiel #21
0
  /**
   * Take a snapshot based on the enabled/disabled state of the table.
   *
   * @param snapshot
   * @throws HBaseSnapshotException when a snapshot specific exception occurs.
   * @throws IOException when some sort of generic IO exception occurs.
   */
  public void takeSnapshot(SnapshotDescription snapshot) throws IOException {
    // check to see if we already completed the snapshot
    if (isSnapshotCompleted(snapshot)) {
      throw new SnapshotExistsException(
          "Snapshot '" + snapshot.getName() + "' already stored on the filesystem.",
          ProtobufUtil.createSnapshotDesc(snapshot));
    }

    LOG.debug("No existing snapshot, attempting snapshot...");

    // stop tracking "abandoned" handlers
    cleanupSentinels();

    // check to see if the table exists
    HTableDescriptor desc = null;
    try {
      desc = master.getTableDescriptors().get(TableName.valueOf(snapshot.getTable()));
    } catch (FileNotFoundException e) {
      String msg = "Table:" + snapshot.getTable() + " info doesn't exist!";
      LOG.error(msg);
      throw new SnapshotCreationException(msg, e, ProtobufUtil.createSnapshotDesc(snapshot));
    } catch (IOException e) {
      throw new SnapshotCreationException(
          "Error while geting table description for table " + snapshot.getTable(),
          e,
          ProtobufUtil.createSnapshotDesc(snapshot));
    }
    if (desc == null) {
      throw new SnapshotCreationException(
          "Table '" + snapshot.getTable() + "' doesn't exist, can't take snapshot.",
          ProtobufUtil.createSnapshotDesc(snapshot));
    }
    SnapshotDescription.Builder builder = snapshot.toBuilder();
    // if not specified, set the snapshot format
    if (!snapshot.hasVersion()) {
      builder.setVersion(SnapshotDescriptionUtils.SNAPSHOT_LAYOUT_VERSION);
    }
    User user = RpcServer.getRequestUser();
    if (User.isHBaseSecurityEnabled(master.getConfiguration()) && user != null) {
      builder.setOwner(user.getShortName());
    }
    snapshot = builder.build();

    // call pre coproc hook
    MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost();
    if (cpHost != null) {
      cpHost.preSnapshot(snapshot, desc);
    }

    // if the table is enabled, then have the RS run actually the snapshot work
    TableName snapshotTable = TableName.valueOf(snapshot.getTable());
    if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.ENABLED)) {
      LOG.debug("Table enabled, starting distributed snapshot.");
      snapshotEnabledTable(snapshot);
      LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot));
    }
    // For disabled table, snapshot is created by the master
    else if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.DISABLED)) {
      LOG.debug("Table is disabled, running snapshot entirely on master.");
      snapshotDisabledTable(snapshot);
      LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot));
    } else {
      LOG.error(
          "Can't snapshot table '"
              + snapshot.getTable()
              + "', isn't open or closed, we don't know what to do!");
      TablePartiallyOpenException tpoe =
          new TablePartiallyOpenException(snapshot.getTable() + " isn't fully open.");
      throw new SnapshotCreationException(
          "Table is not entirely open or closed", tpoe, ProtobufUtil.createSnapshotDesc(snapshot));
    }

    // call post coproc hook
    if (cpHost != null) {
      cpHost.postSnapshot(snapshot, desc);
    }
  }
  @Override
  public void secureBulkLoadHFiles(
      RpcController controller,
      SecureBulkLoadHFilesRequest request,
      RpcCallback<SecureBulkLoadHFilesResponse> done) {
    final List<Pair<byte[], String>> familyPaths = new ArrayList<Pair<byte[], String>>();
    for (ClientProtos.BulkLoadHFileRequest.FamilyPath el : request.getFamilyPathList()) {
      familyPaths.add(new Pair(el.getFamily().toByteArray(), el.getPath()));
    }

    Token userToken = null;
    if (userProvider.isHadoopSecurityEnabled()) {
      userToken =
          new Token(
              request.getFsToken().getIdentifier().toByteArray(),
              request.getFsToken().getPassword().toByteArray(),
              new Text(request.getFsToken().getKind()),
              new Text(request.getFsToken().getService()));
    }
    final String bulkToken = request.getBulkToken();
    User user = getActiveUser();
    final UserGroupInformation ugi = user.getUGI();
    if (userToken != null) {
      ugi.addToken(userToken);
    } else if (userProvider.isHadoopSecurityEnabled()) {
      // we allow this to pass through in "simple" security mode
      // for mini cluster testing
      ResponseConverter.setControllerException(
          controller, new DoNotRetryIOException("User token cannot be null"));
      done.run(SecureBulkLoadHFilesResponse.newBuilder().setLoaded(false).build());
      return;
    }

    HRegion region = env.getRegion();
    boolean bypass = false;
    if (region.getCoprocessorHost() != null) {
      try {
        bypass = region.getCoprocessorHost().preBulkLoadHFile(familyPaths);
      } catch (IOException e) {
        ResponseConverter.setControllerException(controller, e);
        done.run(SecureBulkLoadHFilesResponse.newBuilder().setLoaded(false).build());
        return;
      }
    }
    boolean loaded = false;
    if (!bypass) {
      // Get the target fs (HBase region server fs) delegation token
      // Since we have checked the permission via 'preBulkLoadHFile', now let's give
      // the 'request user' necessary token to operate on the target fs.
      // After this point the 'doAs' user will hold two tokens, one for the source fs
      // ('request user'), another for the target fs (HBase region server principal).
      if (userProvider.isHadoopSecurityEnabled()) {
        FsDelegationToken targetfsDelegationToken = new FsDelegationToken(userProvider, "renewer");
        try {
          targetfsDelegationToken.acquireDelegationToken(fs);
        } catch (IOException e) {
          ResponseConverter.setControllerException(controller, e);
          done.run(SecureBulkLoadHFilesResponse.newBuilder().setLoaded(false).build());
          return;
        }
        Token<?> targetFsToken = targetfsDelegationToken.getUserToken();
        if (targetFsToken != null
            && (userToken == null || !targetFsToken.getService().equals(userToken.getService()))) {
          ugi.addToken(targetFsToken);
        }
      }

      loaded =
          ugi.doAs(
              new PrivilegedAction<Boolean>() {
                @Override
                public Boolean run() {
                  FileSystem fs = null;
                  try {
                    Configuration conf = env.getConfiguration();
                    fs = FileSystem.get(conf);
                    for (Pair<byte[], String> el : familyPaths) {
                      Path p = new Path(el.getSecond());
                      Path stageFamily = new Path(bulkToken, Bytes.toString(el.getFirst()));
                      if (!fs.exists(stageFamily)) {
                        fs.mkdirs(stageFamily);
                        fs.setPermission(stageFamily, PERM_ALL_ACCESS);
                      }
                    }
                    // We call bulkLoadHFiles as requesting user
                    // To enable access prior to staging
                    return env.getRegion()
                        .bulkLoadHFiles(
                            familyPaths, true, new SecureBulkLoadListener(fs, bulkToken, conf));
                  } catch (Exception e) {
                    LOG.error("Failed to complete bulk load", e);
                  }
                  return false;
                }
              });
    }
    if (region.getCoprocessorHost() != null) {
      try {
        loaded = region.getCoprocessorHost().postBulkLoadHFile(familyPaths, loaded);
      } catch (IOException e) {
        ResponseConverter.setControllerException(controller, e);
        done.run(SecureBulkLoadHFilesResponse.newBuilder().setLoaded(false).build());
        return;
      }
    }
    done.run(SecureBulkLoadHFilesResponse.newBuilder().setLoaded(loaded).build());
  }
Beispiel #23
0
  @BeforeClass
  public static void beforeClass() throws Exception {
    conf = UTIL.getConfiguration();
    enableSecurity(conf);

    SUPERUSER = User.createUserForTesting(conf, "admin", new String[] {"supergroup"});
    // Users with global permissions
    USER_GLOBAL_ADMIN = User.createUserForTesting(conf, "global_admin", new String[0]);
    USER_GLOBAL_CREATE = User.createUserForTesting(conf, "global_create", new String[0]);
    USER_GLOBAL_WRITE = User.createUserForTesting(conf, "global_write", new String[0]);
    USER_GLOBAL_READ = User.createUserForTesting(conf, "global_read", new String[0]);
    USER_GLOBAL_EXEC = User.createUserForTesting(conf, "global_exec", new String[0]);

    USER_NS_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
    USER_NS_CREATE = User.createUserForTesting(conf, "namespace_create", new String[0]);
    USER_NS_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
    USER_NS_READ = User.createUserForTesting(conf, "namespace_read", new String[0]);
    USER_NS_EXEC = User.createUserForTesting(conf, "namespace_exec", new String[0]);

    USER_TABLE_CREATE = User.createUserForTesting(conf, "table_create", new String[0]);
    USER_TABLE_WRITE = User.createUserForTesting(conf, "table_write", new String[0]);

    USER_GROUP_ADMIN =
        User.createUserForTesting(conf, "user_group_admin", new String[] {GROUP_ADMIN});
    USER_GROUP_NS_ADMIN =
        User.createUserForTesting(conf, "user_group_ns_admin", new String[] {GROUP_NS_ADMIN});
    USER_GROUP_CREATE =
        User.createUserForTesting(conf, "user_group_create", new String[] {GROUP_CREATE});
    USER_GROUP_READ = User.createUserForTesting(conf, "user_group_read", new String[] {GROUP_READ});
    USER_GROUP_WRITE =
        User.createUserForTesting(conf, "user_group_write", new String[] {GROUP_WRITE});
    // TODO: other table perms

    UTIL.startMiniCluster();
    // Wait for the ACL table to become available
    UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME.getName(), 30 * 1000);

    ACCESS_CONTROLLER =
        (AccessController)
            UTIL.getMiniHBaseCluster()
                .getMaster()
                .getRegionServerCoprocessorHost()
                .findCoprocessor(AccessController.class.getName());

    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build());
    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build());

    // grants on global
    grantGlobal(UTIL, USER_GLOBAL_ADMIN.getShortName(), Permission.Action.ADMIN);
    grantGlobal(UTIL, USER_GLOBAL_CREATE.getShortName(), Permission.Action.CREATE);
    grantGlobal(UTIL, USER_GLOBAL_WRITE.getShortName(), Permission.Action.WRITE);
    grantGlobal(UTIL, USER_GLOBAL_READ.getShortName(), Permission.Action.READ);
    grantGlobal(UTIL, USER_GLOBAL_EXEC.getShortName(), Permission.Action.EXEC);

    // grants on namespace
    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN);
    grantOnNamespace(UTIL, USER_NS_CREATE.getShortName(), TEST_NAMESPACE, Permission.Action.CREATE);
    grantOnNamespace(UTIL, USER_NS_WRITE.getShortName(), TEST_NAMESPACE, Permission.Action.WRITE);
    grantOnNamespace(UTIL, USER_NS_READ.getShortName(), TEST_NAMESPACE, Permission.Action.READ);
    grantOnNamespace(UTIL, USER_NS_EXEC.getShortName(), TEST_NAMESPACE, Permission.Action.EXEC);
    grantOnNamespace(UTIL, toGroupEntry(GROUP_NS_ADMIN), TEST_NAMESPACE, Permission.Action.ADMIN);

    grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN);

    grantGlobal(UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN);
    grantGlobal(UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE);
    grantGlobal(UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ);
    grantGlobal(UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE);
  }
  @Test
  public void testACLTableAccess() throws Exception {
    final Configuration conf = TEST_UTIL.getConfiguration();

    // Superuser
    User superUser = User.createUserForTesting(conf, "admin", new String[] {"supergroup"});

    // Global users
    User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]);
    User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]);
    User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]);
    User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE);
    SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN);

    // Namespace users
    User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]);
    User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]);
    User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]);
    User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsRead.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.READ);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsWrite.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.WRITE);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsCreate.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.CREATE);
    SecureTestUtil.grantOnNamespace(
        TEST_UTIL,
        nsAdmin.getShortName(),
        TEST_TABLE.getTableName().getNamespaceAsString(),
        Action.ADMIN);

    // Table users
    User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]);
    User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]);
    User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]);
    User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableRead.getShortName(), TEST_TABLE.getTableName(), null, null, Action.READ);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableWrite.getShortName(), TEST_TABLE.getTableName(), null, null, Action.WRITE);
    SecureTestUtil.grantOnTable(
        TEST_UTIL,
        tableCreate.getShortName(),
        TEST_TABLE.getTableName(),
        null,
        null,
        Action.CREATE);
    SecureTestUtil.grantOnTable(
        TEST_UTIL, tableAdmin.getShortName(), TEST_TABLE.getTableName(), null, null, Action.ADMIN);

    // Write tests

    AccessTestAction writeAction =
        new AccessTestAction() {
          @Override
          public Object run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf);
                Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
              t.put(
                  new Put(TEST_ROW)
                      .add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER, TEST_VALUE));
              return null;
            } finally {
            }
          }
        };

    // All writes to ACL table denied except for GLOBAL WRITE permission and superuser

    verifyDenied(writeAction, globalAdmin, globalCreate, globalRead);
    verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite);
    verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite);
    verifyAllowed(writeAction, superUser, globalWrite);

    // Read tests

    AccessTestAction scanAction =
        new AccessTestAction() {
          @Override
          public Object run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf);
                Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
              ResultScanner s = t.getScanner(new Scan());
              try {
                for (Result r = s.next(); r != null; r = s.next()) {
                  // do nothing
                }
              } finally {
                s.close();
              }
              return null;
            }
          }
        };

    // All reads from ACL table denied except for GLOBAL READ and superuser

    verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite);
    verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite);
    verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite);
    verifyAllowed(scanAction, superUser, globalRead);
  }
  @Test
  public void testManageUserAuths() throws Throwable {
    // Even though authorization is disabled, we should be able to manage user auths

    SUPERUSER.runAs(
        new PrivilegedExceptionAction<Void>() {
          public Void run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf)) {
              VisibilityClient.setAuths(
                  conn, new String[] {SECRET, CONFIDENTIAL}, USER_RW.getShortName());
            } catch (Throwable t) {
              fail("Should not have failed");
            }
            return null;
          }
        });

    PrivilegedExceptionAction<List<String>> getAuths =
        new PrivilegedExceptionAction<List<String>>() {
          public List<String> run() throws Exception {
            GetAuthsResponse authsResponse = null;
            try (Connection conn = ConnectionFactory.createConnection(conf)) {
              authsResponse = VisibilityClient.getAuths(conn, USER_RW.getShortName());
            } catch (Throwable t) {
              fail("Should not have failed");
            }
            List<String> authsList = new ArrayList<String>();
            for (ByteString authBS : authsResponse.getAuthList()) {
              authsList.add(Bytes.toString(authBS.toByteArray()));
            }
            return authsList;
          }
        };

    List<String> authsList = SUPERUSER.runAs(getAuths);
    assertEquals(2, authsList.size());
    assertTrue(authsList.contains(SECRET));
    assertTrue(authsList.contains(CONFIDENTIAL));

    SUPERUSER.runAs(
        new PrivilegedExceptionAction<Void>() {
          public Void run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf)) {
              VisibilityClient.clearAuths(conn, new String[] {SECRET}, USER_RW.getShortName());
            } catch (Throwable t) {
              fail("Should not have failed");
            }
            return null;
          }
        });

    authsList = SUPERUSER.runAs(getAuths);
    assertEquals(1, authsList.size());
    assertTrue(authsList.contains(CONFIDENTIAL));

    SUPERUSER.runAs(
        new PrivilegedExceptionAction<Void>() {
          public Void run() throws Exception {
            try (Connection conn = ConnectionFactory.createConnection(conf)) {
              VisibilityClient.clearAuths(
                  conn, new String[] {CONFIDENTIAL}, USER_RW.getShortName());
            } catch (Throwable t) {
              fail("Should not have failed");
            }
            return null;
          }
        });

    authsList = SUPERUSER.runAs(getAuths);
    assertEquals(0, authsList.size());
  }