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:
parent
8375bfcba9
commit
86592b6103
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue