HBASE-5449 Support for wire-compatible security functionality

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1377141 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2012-08-24 22:43:19 +00:00
parent 8375bfcba9
commit 86592b6103
7 changed files with 313 additions and 79 deletions

View File

@ -27,6 +27,7 @@ import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -107,12 +108,19 @@ import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionLoad;
import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.CreateTableRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.GetTableDescriptorsResponse;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
import org.apache.hadoop.hbase.regionserver.wal.HLog;
import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.TablePermission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.protobuf.ByteString;
import com.google.protobuf.Message;
import com.google.protobuf.ServiceException;
@ -1482,4 +1490,224 @@ public final class ProtobufUtil {
baos.close();
return ProtobufUtil.prependPBMagic(baos.toByteArray());
}
/**
* Converts a Permission proto to a client Permission object.
*
* @param proto the protobuf Permission
* @return the converted Permission
*/
public static Permission toPermission(AccessControlProtos.Permission proto) {
if (proto.hasTable()) {
return toTablePermission(proto);
} else {
List<Permission.Action> actions = toPermissionActions(proto.getActionList());
return new Permission(actions.toArray(new Permission.Action[actions.size()]));
}
}
/**
* Converts a Permission proto to a client TablePermission object.
*
* @param proto the protobuf Permission
* @return the converted TablePermission
*/
public static TablePermission toTablePermission(AccessControlProtos.Permission proto) {
List<Permission.Action> actions = toPermissionActions(proto.getActionList());
byte[] qualifier = null;
byte[] family = null;
byte[] table = null;
if (proto.hasTable()) table = proto.getTable().toByteArray();
if (proto.hasFamily()) family = proto.getFamily().toByteArray();
if (proto.hasQualifier()) qualifier = proto.getQualifier().toByteArray();
return new TablePermission(table, family, qualifier,
actions.toArray(new Permission.Action[actions.size()]));
}
/**
* Convert a client Permission to a Permission proto
*
* @param action the client Permission
* @return the protobuf Permission
*/
public static AccessControlProtos.Permission toPermission(Permission perm) {
AccessControlProtos.Permission.Builder builder = AccessControlProtos.Permission.newBuilder();
if (perm instanceof TablePermission) {
TablePermission tablePerm = (TablePermission)perm;
if (tablePerm.hasTable()) {
builder.setTable(ByteString.copyFrom(tablePerm.getTable()));
}
if (tablePerm.hasFamily()) {
builder.setFamily(ByteString.copyFrom(tablePerm.getFamily()));
}
if (tablePerm.hasQualifier()) {
builder.setQualifier(ByteString.copyFrom(tablePerm.getQualifier()));
}
}
for (Permission.Action a : perm.getActions()) {
builder.addAction(toPermissionAction(a));
}
return builder.build();
}
/**
* Converts a list of Permission.Action proto to a list of client Permission.Action objects.
*
* @param protoActions the list of protobuf Actions
* @return the converted list of Actions
*/
public static List<Permission.Action> toPermissionActions(
List<AccessControlProtos.Permission.Action> protoActions) {
List<Permission.Action> actions = new ArrayList<Permission.Action>(protoActions.size());
for (AccessControlProtos.Permission.Action a : protoActions) {
actions.add(toPermissionAction(a));
}
return actions;
}
/**
* Converts a Permission.Action proto to a client Permission.Action object.
*
* @param proto the protobuf Action
* @return the converted Action
*/
public static Permission.Action toPermissionAction(
AccessControlProtos.Permission.Action action) {
switch (action) {
case READ:
return Permission.Action.READ;
case WRITE:
return Permission.Action.WRITE;
case EXEC:
return Permission.Action.EXEC;
case CREATE:
return Permission.Action.CREATE;
case ADMIN:
return Permission.Action.ADMIN;
}
throw new IllegalArgumentException("Unknown action value "+action.name());
}
/**
* Convert a client Permission.Action to a Permission.Action proto
*
* @param action the client Action
* @return the protobuf Action
*/
public static AccessControlProtos.Permission.Action toPermissionAction(
Permission.Action action) {
switch (action) {
case READ:
return AccessControlProtos.Permission.Action.READ;
case WRITE:
return AccessControlProtos.Permission.Action.WRITE;
case EXEC:
return AccessControlProtos.Permission.Action.EXEC;
case CREATE:
return AccessControlProtos.Permission.Action.CREATE;
case ADMIN:
return AccessControlProtos.Permission.Action.ADMIN;
}
throw new IllegalArgumentException("Unknown action value "+action.name());
}
/**
* Convert a client user permission to a user permission proto
*
* @param perm the client UserPermission
* @return the protobuf UserPermission
*/
public static AccessControlProtos.UserPermission toUserPermission(UserPermission perm) {
AccessControlProtos.Permission.Builder permissionBuilder =
AccessControlProtos.Permission.newBuilder();
for (Permission.Action a : perm.getActions()) {
permissionBuilder.addAction(toPermissionAction(a));
}
if (perm.hasTable()) {
permissionBuilder.setTable(ByteString.copyFrom(perm.getTable()));
}
if (perm.hasFamily()) {
permissionBuilder.setFamily(ByteString.copyFrom(perm.getFamily()));
}
if (perm.hasQualifier()) {
permissionBuilder.setQualifier(ByteString.copyFrom(perm.getQualifier()));
}
return AccessControlProtos.UserPermission.newBuilder()
.setUser(ByteString.copyFrom(perm.getUser()))
.setPermission(permissionBuilder)
.build();
}
/**
* Converts a user permission proto to a client user permission object.
*
* @param proto the protobuf UserPermission
* @return the converted UserPermission
*/
public static UserPermission toUserPermission(AccessControlProtos.UserPermission proto) {
AccessControlProtos.Permission permission = proto.getPermission();
List<Permission.Action> actions = toPermissionActions(permission.getActionList());
byte[] qualifier = null;
byte[] family = null;
byte[] table = null;
if (permission.hasTable()) table = permission.getTable().toByteArray();
if (permission.hasFamily()) family = permission.getFamily().toByteArray();
if (permission.hasQualifier()) qualifier = permission.getQualifier().toByteArray();
return new UserPermission(proto.getUser().toByteArray(),
table, family, qualifier,
actions.toArray(new Permission.Action[actions.size()]));
}
/**
* Convert a ListMultimap<String, TablePermission> where key is username
* to a protobuf UserPermission
*
* @param perm the list of user and table permissions
* @return the protobuf UserTablePermissions
*/
public static AccessControlProtos.UserTablePermissions toUserTablePermissions(
ListMultimap<String, TablePermission> perm) {
AccessControlProtos.UserTablePermissions.Builder builder =
AccessControlProtos.UserTablePermissions.newBuilder();
for (Map.Entry<String, Collection<TablePermission>> entry : perm.asMap().entrySet()) {
AccessControlProtos.UserTablePermissions.UserPermissions.Builder userPermBuilder =
AccessControlProtos.UserTablePermissions.UserPermissions.newBuilder();
userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
for (TablePermission tablePerm: entry.getValue()) {
userPermBuilder.addPermissions(toPermission(tablePerm));
}
builder.addPermissions(userPermBuilder.build());
}
return builder.build();
}
/**
* Convert a protobuf UserTablePermissions to a
* ListMultimap<String, TablePermission> where key is username.
*
* @param proto the protobuf UserPermission
* @return the converted UserPermission
*/
public static ListMultimap<String, TablePermission> toUserTablePermissions(
AccessControlProtos.UserTablePermissions proto) {
ListMultimap<String, TablePermission> perms = ArrayListMultimap.create();
AccessControlProtos.UserTablePermissions.UserPermissions userPerm;
for (int i = 0; i < proto.getPermissionsCount(); i++) {
userPerm = proto.getPermissions(i);
for (int j = 0; j < userPerm.getPermissionsCount(); j++) {
TablePermission tablePerm = toTablePermission(userPerm.getPermissions(j));
perms.put(userPerm.getUser().toStringUtf8(), tablePerm);
}
}
return perms;
}
}

View File

@ -620,6 +620,7 @@ public class ReplicationSource extends Thread
}
this.totalReplicatedEdits += currentNbEntries;
this.metrics.shipBatch(this.currentNbOperations);
this.currentNbOperations = 0;
this.metrics.setAgeOfLastShippedOp(
this.entriesArray[currentNbEntries-1].getKey().getWriteTime());
LOG.debug("Replicated in total: " + this.totalReplicatedEdits);

View File

@ -18,11 +18,13 @@
package org.apache.hadoop.hbase.security.access;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.DeserializationException;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
@ -44,14 +46,15 @@ import org.apache.hadoop.hbase.regionserver.StoreFile;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.RegexStringComparator;
import org.apache.hadoop.hbase.filter.QualifierFilter;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.io.Text;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.*;
@ -501,58 +504,47 @@ public class AccessControlLists {
username, new TablePermission(table, permFamily, permQualifier, value));
}
/**
* Writes a set of permissions as {@link org.apache.hadoop.io.Writable} instances
* to the given output stream.
* @param out
* @param perms
* @param conf
* @throws IOException
*/
public static void writePermissions(DataOutput out,
ListMultimap<String,? extends Permission> perms, Configuration conf)
throws IOException {
Set<String> keys = perms.keySet();
out.writeInt(keys.size());
for (String key : keys) {
Text.writeString(out, key);
HbaseObjectWritable.writeObject(out, perms.get(key), List.class, conf);
}
}
/**
* Writes a set of permissions as {@link org.apache.hadoop.io.Writable} instances
* and returns the resulting byte array.
*
* Writes a set of permission [user: table permission]
*/
public static byte[] writePermissionsAsBytes(
ListMultimap<String,? extends Permission> perms, Configuration conf) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
writePermissions(new DataOutputStream(bos), perms, conf);
return bos.toByteArray();
} catch (IOException ioe) {
// shouldn't happen here
LOG.error("Error serializing permissions", ioe);
}
return null;
public static byte[] writePermissionsAsBytes(ListMultimap<String, TablePermission> perms, Configuration conf) {
return ProtobufUtil.prependPBMagic(ProtobufUtil.toUserTablePermissions(perms).toByteArray());
}
/**
* Reads a set of permissions as {@link org.apache.hadoop.io.Writable} instances
* from the input stream.
*/
public static <T extends Permission> ListMultimap<String,T> readPermissions(
DataInput in, Configuration conf) throws IOException {
ListMultimap<String,T> perms = ArrayListMultimap.create();
int length = in.readInt();
for (int i=0; i<length; i++) {
String user = Text.readString(in);
List<T> userPerms =
(List)HbaseObjectWritable.readObject(in, conf);
perms.putAll(user, userPerms);
public static ListMultimap<String, TablePermission> readPermissions(byte[] data,
Configuration conf) throws DeserializationException {
if (ProtobufUtil.isPBMagicPrefix(data)) {
int pblen = ProtobufUtil.lengthOfPBMagic();
try {
AccessControlProtos.UserTablePermissions perms =
AccessControlProtos.UserTablePermissions.newBuilder().mergeFrom(
data, pblen, data.length - pblen).build();
return ProtobufUtil.toUserTablePermissions(perms);
} catch (InvalidProtocolBufferException e) {
throw new DeserializationException(e);
}
} else {
ListMultimap<String,TablePermission> perms = ArrayListMultimap.create();
try {
DataInput in = new DataInputStream(new ByteArrayInputStream(data));
int length = in.readInt();
for (int i=0; i<length; i++) {
String user = Text.readString(in);
List<TablePermission> userPerms = (List)HbaseObjectWritable.readObject(in, conf);
perms.putAll(user, userPerms);
}
} catch (IOException e) {
throw new DeserializationException(e);
}
return perms;
}
return perms;
}
/**

View File

@ -199,8 +199,7 @@ public class AccessController extends BaseRegionObserver
tables.entrySet()) {
byte[] table = t.getKey();
ListMultimap<String,TablePermission> perms = t.getValue();
byte[] serialized = AccessControlLists.writePermissionsAsBytes(perms,
regionEnv.getConfiguration());
byte[] serialized = AccessControlLists.writePermissionsAsBytes(perms, e.getConfiguration());
this.authManager.getZKPermissionWatcher().writeToZookeeper(table, serialized);
}
}
@ -252,7 +251,7 @@ public class AccessController extends BaseRegionObserver
* the request
* @return
*/
AuthResult permissionGranted(User user, TablePermission.Action permRequest,
AuthResult permissionGranted(User user, Permission.Action permRequest,
RegionCoprocessorEnvironment e,
Map<byte [], ? extends Collection<?>> families) {
HRegionInfo hri = e.getRegion().getRegionInfo();
@ -261,7 +260,7 @@ public class AccessController extends BaseRegionObserver
// 1. All users need read access to .META. and -ROOT- tables.
// this is a very common operation, so deal with it quickly.
if (hri.isRootRegion() || hri.isMetaRegion()) {
if (permRequest == TablePermission.Action.READ) {
if (permRequest == Permission.Action.READ) {
return AuthResult.allow("All users allowed", user, permRequest, tableName);
}
}
@ -275,7 +274,7 @@ public class AccessController extends BaseRegionObserver
// so the user need to be allowed to write on it.
// e.g. When a table is removed an entry is removed from .META. and _acl_
// and the user need to be allowed to write on both tables.
if (permRequest == TablePermission.Action.WRITE &&
if (permRequest == Permission.Action.WRITE &&
(hri.isRootRegion() || hri.isMetaRegion() ||
Bytes.equals(tableName, AccessControlLists.ACL_GLOBAL_NAME)) &&
(authManager.authorize(user, Permission.Action.CREATE) ||
@ -364,7 +363,6 @@ public class AccessController extends BaseRegionObserver
// for non-rpc handling, fallback to system user
user = User.getCurrent();
}
return user;
}
@ -473,7 +471,7 @@ public class AccessController extends BaseRegionObserver
* over at least one of the column qualifiers in the given column families.
*/
private boolean hasFamilyQualifierPermission(User user,
TablePermission.Action perm,
Permission.Action perm,
RegionCoprocessorEnvironment env,
Map<byte[], ? extends Set<byte[]>> familyMap)
throws IOException {
@ -823,7 +821,7 @@ public class AccessController extends BaseRegionObserver
public void preGetClosestRowBefore(final ObserverContext<RegionCoprocessorEnvironment> c,
final byte [] row, final byte [] family, final Result result)
throws IOException {
requirePermission(TablePermission.Action.READ, c.getEnvironment(),
requirePermission(Permission.Action.READ, c.getEnvironment(),
(family != null ? Lists.newArrayList(family) : null));
}
@ -837,10 +835,10 @@ public class AccessController extends BaseRegionObserver
RegionCoprocessorEnvironment e = c.getEnvironment();
User requestUser = getActiveUser();
AuthResult authResult = permissionGranted(requestUser,
TablePermission.Action.READ, e, get.getFamilyMap());
Permission.Action.READ, e, get.getFamilyMap());
if (!authResult.isAllowed()) {
if (hasFamilyQualifierPermission(requestUser,
TablePermission.Action.READ, e, get.getFamilyMap())) {
Permission.Action.READ, e, get.getFamilyMap())) {
byte[] table = getTableName(e);
AccessControlFilter filter = new AccessControlFilter(authManager,
requestUser, table);
@ -854,7 +852,7 @@ public class AccessController extends BaseRegionObserver
get.setFilter(filter);
}
logResult(AuthResult.allow("Access allowed with filter", requestUser,
TablePermission.Action.READ, authResult.table));
Permission.Action.READ, authResult.table));
} else {
logResult(authResult);
throw new AccessDeniedException("Insufficient permissions (table=" +
@ -869,7 +867,7 @@ public class AccessController extends BaseRegionObserver
@Override
public boolean preExists(final ObserverContext<RegionCoprocessorEnvironment> c,
final Get get, final boolean exists) throws IOException {
requirePermission(TablePermission.Action.READ, c.getEnvironment(),
requirePermission(Permission.Action.READ, c.getEnvironment(),
get.familySet());
return exists;
}
@ -878,7 +876,7 @@ public class AccessController extends BaseRegionObserver
public void prePut(final ObserverContext<RegionCoprocessorEnvironment> c,
final Put put, final WALEdit edit, final boolean writeToWAL)
throws IOException {
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(),
requirePermission(Permission.Action.WRITE, c.getEnvironment(),
put.getFamilyMap());
}
@ -894,7 +892,7 @@ public class AccessController extends BaseRegionObserver
public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> c,
final Delete delete, final WALEdit edit, final boolean writeToWAL)
throws IOException {
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(),
requirePermission(Permission.Action.WRITE, c.getEnvironment(),
delete.getFamilyMap());
}
@ -914,8 +912,8 @@ public class AccessController extends BaseRegionObserver
final WritableByteArrayComparable comparator, final Put put,
final boolean result) throws IOException {
Collection<byte[]> familyMap = Arrays.asList(new byte[][]{family});
requirePermission(TablePermission.Action.READ, c.getEnvironment(), familyMap);
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(), familyMap);
requirePermission(Permission.Action.READ, c.getEnvironment(), familyMap);
requirePermission(Permission.Action.WRITE, c.getEnvironment(), familyMap);
return result;
}
@ -926,8 +924,8 @@ public class AccessController extends BaseRegionObserver
final WritableByteArrayComparable comparator, final Delete delete,
final boolean result) throws IOException {
Collection<byte[]> familyMap = Arrays.asList(new byte[][]{family});
requirePermission(TablePermission.Action.READ, c.getEnvironment(), familyMap);
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(), familyMap);
requirePermission(Permission.Action.READ, c.getEnvironment(), familyMap);
requirePermission(Permission.Action.WRITE, c.getEnvironment(), familyMap);
return result;
}
@ -936,7 +934,7 @@ public class AccessController extends BaseRegionObserver
final byte [] row, final byte [] family, final byte [] qualifier,
final long amount, final boolean writeToWAL)
throws IOException {
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(),
requirePermission(Permission.Action.WRITE, c.getEnvironment(),
Arrays.asList(new byte[][]{family}));
return -1;
}
@ -944,7 +942,7 @@ public class AccessController extends BaseRegionObserver
@Override
public Result preAppend(ObserverContext<RegionCoprocessorEnvironment> c, Append append)
throws IOException {
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(), append.getFamilyMap());
requirePermission(Permission.Action.WRITE, c.getEnvironment(), append.getFamilyMap());
return null;
}
@ -952,7 +950,7 @@ public class AccessController extends BaseRegionObserver
public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> c,
final Increment increment)
throws IOException {
requirePermission(TablePermission.Action.WRITE, c.getEnvironment(),
requirePermission(Permission.Action.WRITE, c.getEnvironment(),
increment.getFamilyMap().keySet());
return null;
}
@ -966,10 +964,10 @@ public class AccessController extends BaseRegionObserver
*/
RegionCoprocessorEnvironment e = c.getEnvironment();
User user = getActiveUser();
AuthResult authResult = permissionGranted(user, TablePermission.Action.READ, e,
AuthResult authResult = permissionGranted(user, Permission.Action.READ, e,
scan.getFamilyMap());
if (!authResult.isAllowed()) {
if (hasFamilyQualifierPermission(user, TablePermission.Action.READ, e,
if (hasFamilyQualifierPermission(user, Permission.Action.READ, e,
scan.getFamilyMap())) {
byte[] table = getTableName(e);
AccessControlFilter filter = new AccessControlFilter(authManager,
@ -984,7 +982,7 @@ public class AccessController extends BaseRegionObserver
scan.setFilter(filter);
}
logResult(AuthResult.allow("Access allowed with filter", user,
TablePermission.Action.READ, authResult.table));
Permission.Action.READ, authResult.table));
} else {
// no table/family level perms and no qualifier level perms, reject
logResult(authResult);

View File

@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.DeserializationException;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.util.Bytes;
@ -101,8 +102,13 @@ public class TableAuthManager {
public void refreshCacheFromWritable(byte[] table, byte[] data) throws IOException {
if (data != null && data.length > 0) {
DataInput in = new DataInputStream(new ByteArrayInputStream(data));
ListMultimap<String,TablePermission> perms = AccessControlLists.readPermissions(in, conf);
ListMultimap<String,TablePermission> perms;
try {
perms = AccessControlLists.readPermissions(data, conf);
} catch (DeserializationException e) {
throw new IOException(e);
}
if (perms != null) {
if (Bytes.equals(table, AccessControlLists.ACL_GLOBAL_NAME)) {
updateGlobalCache(perms);
@ -250,7 +256,7 @@ public class TableAuthManager {
}
public boolean authorize(User user, byte[] table, KeyValue kv,
TablePermission.Action action) {
Permission.Action action) {
List<TablePermission> userPerms = getUserPermissions(
user.getShortName(), table);
if (authorize(userPerms, table, kv, action)) {
@ -271,7 +277,7 @@ public class TableAuthManager {
}
private boolean authorize(List<TablePermission> perms, byte[] table, KeyValue kv,
TablePermission.Action action) {
Permission.Action action) {
if (perms != null) {
for (TablePermission p : perms) {
if (p.implies(table, kv, action)) {
@ -375,7 +381,7 @@ public class TableAuthManager {
* authorize() on the same column family would return true.
*/
public boolean matchPermission(User user,
byte[] table, byte[] family, TablePermission.Action action) {
byte[] table, byte[] family, Permission.Action action) {
List<TablePermission> userPerms = getUserPermissions(
user.getShortName(), table);
if (userPerms != null) {
@ -405,7 +411,7 @@ public class TableAuthManager {
public boolean matchPermission(User user,
byte[] table, byte[] family, byte[] qualifier,
TablePermission.Action action) {
Permission.Action action) {
List<TablePermission> userPerms = getUserPermissions(
user.getShortName(), table);
if (userPerms != null) {

View File

@ -86,14 +86,26 @@ public class TablePermission extends Permission {
this.qualifier = qualifier;
}
public boolean hasTable() {
return table != null;
}
public byte[] getTable() {
return table;
}
public boolean hasFamily() {
return family != null;
}
public byte[] getFamily() {
return family;
}
public boolean hasQualifier() {
return qualifier != null;
}
public byte[] getQualifier() {
return qualifier;
}

View File

@ -252,13 +252,10 @@ public class TestTablePermissions {
permissions.put("hubert", new TablePermission(TEST_TABLE2, null,
TablePermission.Action.READ, TablePermission.Action.WRITE));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
AccessControlLists.writePermissions(new DataOutputStream(bos),
permissions, conf);
byte[] permsData = AccessControlLists.writePermissionsAsBytes(permissions, conf);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ListMultimap<String,TablePermission> copy =
AccessControlLists.readPermissions(new DataInputStream(bis), conf);
AccessControlLists.readPermissions(permsData, conf);
checkMultimapEqual(permissions, copy);
}