From d4e08292b7dfb2c3bc367c8c1b4067d1dcd29906 Mon Sep 17 00:00:00 2001 From: jxiang Date: Wed, 19 Dec 2012 17:16:49 +0000 Subject: [PATCH] HBASE-6887 Convert security-related shell commands to use PB-based AccessControlService git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1423965 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop/hbase/protobuf/ProtobufUtil.java | 89 ++++++- .../hbase/protobuf/RequestConverter.java | 73 ++++++ .../security/access/AccessController.java | 235 ++++++------------ .../access/AccessControllerProtocol.java | 110 -------- hbase-server/src/main/ruby/hbase/security.rb | 109 ++++---- .../access/TestAccessControlFilter.java | 20 +- .../security/access/TestAccessController.java | 229 ++++++++--------- 7 files changed, 412 insertions(+), 453 deletions(-) delete mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java index 802f907e0b5..3fdb0da6fb2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java @@ -75,6 +75,7 @@ import org.apache.hadoop.hbase.io.HbaseObjectWritable; import org.apache.hadoop.hbase.io.TimeRange; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos; +import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest; @@ -134,6 +135,7 @@ import org.apache.hbase.Cell; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; import com.google.protobuf.ByteString; import com.google.protobuf.Message; import com.google.protobuf.RpcChannel; @@ -1791,6 +1793,91 @@ public final class ProtobufUtil { return builder.build(); } + /** + * A utility used to grant a user some permissions. The permissions will + * be global if table is not specified. Otherwise, they are for those + * table/column family/qualifier only. + *

+ * It's also called by the shell, in case you want to find references. + * + * @param protocol the AccessControlService protocol proxy + * @param userShortName the short name of the user to grant permissions + * @param t optional table name + * @param f optional column family + * @param q optional qualifier + * @param actions the permissions to be granted + * @throws ServiceException + */ + public static void grant(AccessControlService.BlockingInterface protocol, + String userShortName, byte[] t, byte[] f, byte[] q, + Permission.Action... actions) throws ServiceException { + List permActions = + Lists.newArrayListWithCapacity(actions.length); + for (Permission.Action a : actions) { + permActions.add(ProtobufUtil.toPermissionAction(a)); + } + AccessControlProtos.GrantRequest request = RequestConverter. + buildGrantRequest(userShortName, t, f, q, permActions.toArray( + new AccessControlProtos.Permission.Action[actions.length])); + protocol.grant(null, request); + } + + /** + * A utility used to revoke a user some permissions. The permissions will + * be global if table is not specified. Otherwise, they are for those + * table/column family/qualifier only. + *

+ * It's also called by the shell, in case you want to find references. + * + * @param protocol the AccessControlService protocol proxy + * @param userShortName the short name of the user to revoke permissions + * @param t optional table name + * @param f optional column family + * @param q optional qualifier + * @param actions the permissions to be revoked + * @throws ServiceException + */ + public static void revoke(AccessControlService.BlockingInterface protocol, + String userShortName, byte[] t, byte[] f, byte[] q, + Permission.Action... actions) throws ServiceException { + List permActions = + Lists.newArrayListWithCapacity(actions.length); + for (Permission.Action a : actions) { + permActions.add(ProtobufUtil.toPermissionAction(a)); + } + AccessControlProtos.RevokeRequest request = RequestConverter. + buildRevokeRequest(userShortName, t, f, q, permActions.toArray( + new AccessControlProtos.Permission.Action[actions.length])); + protocol.revoke(null, request); + } + + /** + * A utility used to get user permissions. + *

+ * It's also called by the shell, in case you want to find references. + * + * @param protocol the AccessControlService protocol proxy + * @param t optional table name + * @throws ServiceException + */ + public static List getUserPermissions( + AccessControlService.BlockingInterface protocol, + byte[] t) throws ServiceException { + AccessControlProtos.UserPermissionsRequest.Builder builder = + AccessControlProtos.UserPermissionsRequest.newBuilder(); + if (t != null) { + builder.setTable(ByteString.copyFrom(t)); + } + AccessControlProtos.UserPermissionsRequest request = builder.build(); + AccessControlProtos.UserPermissionsResponse response = + protocol.getUserPermissions(null, request); + List perms = new ArrayList(); + for (AccessControlProtos.UserPermission perm: response.getPermissionList()) { + perms.add(ProtobufUtil.toUserPermission(perm)); + } + return perms; + } + /** * Convert a protobuf UserTablePermissions to a * ListMultimap where key is username. @@ -1912,4 +1999,4 @@ public final class ProtobufUtil { KeyValue.Type.codeToType((byte)kv.getKeyType().getNumber()), kv.getValue().toByteArray()); } -} \ No newline at end of file +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java index 145d4399ce8..8801d51f4c7 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.client.RowMutations; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.coprocessor.Exec; import org.apache.hadoop.hbase.filter.ByteArrayComparable; +import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest; import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest; @@ -1151,6 +1152,78 @@ public final class RequestConverter { ByteString.copyFrom(regionName)).build(); } + /** + * Create a request to grant user permissions. + * + * @param username the short user name who to grant permissions + * @param table optional table name the permissions apply + * @param family optional column family + * @param qualifier optional qualifier + * @param actions the permissions to be granted + * @return A {@link AccessControlProtos.GrantRequest) + */ + public static AccessControlProtos.GrantRequest buildGrantRequest( + String username, byte[] table, byte[] family, byte[] qualifier, + AccessControlProtos.Permission.Action... actions) { + AccessControlProtos.Permission.Builder permissionBuilder = + AccessControlProtos.Permission.newBuilder(); + for (AccessControlProtos.Permission.Action a : actions) { + permissionBuilder.addAction(a); + } + if (table != null) { + permissionBuilder.setTable(ByteString.copyFrom(table)); + } + if (family != null) { + permissionBuilder.setFamily(ByteString.copyFrom(family)); + } + if (qualifier != null) { + permissionBuilder.setQualifier(ByteString.copyFrom(qualifier)); + } + + return AccessControlProtos.GrantRequest.newBuilder() + .setPermission( + AccessControlProtos.UserPermission.newBuilder() + .setUser(ByteString.copyFromUtf8(username)) + .setPermission(permissionBuilder.build()) + ).build(); + } + + /** + * Create a request to revoke user permissions. + * + * @param username the short user name whose permissions to be revoked + * @param table optional table name the permissions apply + * @param family optional column family + * @param qualifier optional qualifier + * @param actions the permissions to be revoked + * @return A {@link AccessControlProtos.RevokeRequest) + */ + public static AccessControlProtos.RevokeRequest buildRevokeRequest( + String username, byte[] table, byte[] family, byte[] qualifier, + AccessControlProtos.Permission.Action... actions) { + AccessControlProtos.Permission.Builder permissionBuilder = + AccessControlProtos.Permission.newBuilder(); + for (AccessControlProtos.Permission.Action a : actions) { + permissionBuilder.addAction(a); + } + if (table != null) { + permissionBuilder.setTable(ByteString.copyFrom(table)); + } + if (family != null) { + permissionBuilder.setFamily(ByteString.copyFrom(family)); + } + if (qualifier != null) { + permissionBuilder.setQualifier(ByteString.copyFrom(qualifier)); + } + + return AccessControlProtos.RevokeRequest.newBuilder() + .setPermission( + AccessControlProtos.UserPermission.newBuilder() + .setUser(ByteString.copyFromUtf8(username)) + .setPermission(permissionBuilder.build()) + ).build(); + } + /** * Create a RegionOpenInfo based on given region info and version of offline node */ diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index 9d4c6045df2..92fc38c7fe1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -47,8 +47,6 @@ import org.apache.hadoop.hbase.coprocessor.*; import org.apache.hadoop.hbase.filter.CompareFilter; import org.apache.hadoop.hbase.filter.FilterList; import org.apache.hadoop.hbase.filter.ByteArrayComparable; -import org.apache.hadoop.hbase.ipc.HBaseRPC; -import org.apache.hadoop.hbase.ipc.ProtocolSignature; import org.apache.hadoop.hbase.ipc.RequestContext; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; @@ -100,14 +98,14 @@ import static org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.Acc * *

* The access control lists used for authorization can be manipulated via the - * exposed {@link AccessControllerProtocol} implementation, and the associated + * exposed {@link AccessControlService.Interface} implementation, and the associated * {@code grant}, {@code revoke}, and {@code user_permission} HBase shell * commands. *

*/ public class AccessController extends BaseRegionObserver - implements MasterObserver, RegionServerObserver, AccessControllerProtocol, - AccessControlService.Interface, CoprocessorService { + implements MasterObserver, RegionServerObserver, + AccessControlService.Interface, CoprocessorService { /** * Represents the result of an authorization check for logging and error * reporting. @@ -180,11 +178,6 @@ public class AccessController extends BaseRegionObserver private static final Log AUDITLOG = LogFactory.getLog("SecurityLogger."+AccessController.class.getName()); - /** - * Version number for AccessControllerProtocol - */ - private static final long PROTOCOL_VERSION = 1L; - TableAuthManager authManager = null; // flags if we are running on a region of the _acl_ table @@ -1079,143 +1072,6 @@ public class AccessController extends BaseRegionObserver } } - /* ---- AccessControllerProtocol implementation ---- */ - /* - * These methods are only allowed to be called against the _acl_ region(s). - * This will be restricted by both client side and endpoint implementations. - */ - @Deprecated - @Override - public void grant(UserPermission perm) throws IOException { - // verify it's only running at .acl. - if (aclRegion) { - if (LOG.isDebugEnabled()) { - LOG.debug("Received request to grant access permission " + perm.toString()); - } - - requirePermission("grant", perm.getTable(), perm.getFamily(), perm.getQualifier(), Action.ADMIN); - - AccessControlLists.addUserPermission(regionEnv.getConfiguration(), perm); - if (AUDITLOG.isTraceEnabled()) { - // audit log should store permission changes in addition to auth results - AUDITLOG.trace("Granted permission " + perm.toString()); - } - } else { - throw new CoprocessorException(AccessController.class, "This method " - + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); - } - } - - @Override - @Deprecated - public void grant(byte[] user, TablePermission permission) - throws IOException { - grant(new UserPermission(user, permission.getTable(), - permission.getFamily(), permission.getQualifier(), - permission.getActions())); - } - - @Deprecated - @Override - public void revoke(UserPermission perm) throws IOException { - // only allowed to be called on _acl_ region - if (aclRegion) { - if (LOG.isDebugEnabled()) { - LOG.debug("Received request to revoke access permission " + perm.toString()); - } - - requirePermission("revoke", perm.getTable(), perm.getFamily(), - perm.getQualifier(), Action.ADMIN); - - AccessControlLists.removeUserPermission(regionEnv.getConfiguration(), perm); - if (AUDITLOG.isTraceEnabled()) { - // audit log should record all permission changes - AUDITLOG.trace("Revoked permission " + perm.toString()); - } - } else { - throw new CoprocessorException(AccessController.class, "This method " - + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); - } - } - - @Override - @Deprecated - public void revoke(byte[] user, TablePermission permission) - throws IOException { - revoke(new UserPermission(user, permission.getTable(), - permission.getFamily(), permission.getQualifier(), - permission.getActions())); - } - - @Deprecated - @Override - public List getUserPermissions(final byte[] tableName) throws IOException { - // only allowed to be called on _acl_ region - if (aclRegion) { - requirePermission("userPermissions", tableName, null, null, Action.ADMIN); - - List perms = AccessControlLists.getUserPermissions( - regionEnv.getConfiguration(), tableName); - return perms; - } else { - throw new CoprocessorException(AccessController.class, "This method " - + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); - } - } - - @Deprecated - @Override - public void checkPermissions(Permission[] permissions) throws IOException { - byte[] tableName = regionEnv.getRegion().getTableDesc().getName(); - for (Permission permission : permissions) { - if (permission instanceof TablePermission) { - TablePermission tperm = (TablePermission) permission; - for (Permission.Action action : permission.getActions()) { - if (!Arrays.equals(tperm.getTable(), tableName)) { - throw new CoprocessorException(AccessController.class, String.format("This method " - + "can only execute at the table specified in TablePermission. " + - "Table of the region:%s , requested table:%s", Bytes.toString(tableName), - Bytes.toString(tperm.getTable()))); - } - - HashMap> familyMap = Maps.newHashMapWithExpectedSize(1); - if (tperm.getFamily() != null) { - if (tperm.getQualifier() != null) { - familyMap.put(tperm.getFamily(), Sets.newHashSet(tperm.getQualifier())); - } else { - familyMap.put(tperm.getFamily(), null); - } - } - - requirePermission("checkPermissions", action, regionEnv, familyMap); - } - - } else { - for (Permission.Action action : permission.getActions()) { - requirePermission("checkPermissions", action); - } - } - } - } - - @Deprecated - @Override - public long getProtocolVersion(String protocol, long clientVersion) throws IOException { - return PROTOCOL_VERSION; - } - - @Deprecated - @Override - public ProtocolSignature getProtocolSignature(String protocol, - long clientVersion, int clientMethodsHash) throws IOException { - if (AccessControllerProtocol.class.getName().equals(protocol)) { - return new ProtocolSignature(PROTOCOL_VERSION, null); - } - throw new HBaseRPC.UnknownProtocolException( - "Unexpected protocol requested: "+protocol); - } - - /* ---- Protobuf AccessControlService implementation ---- */ @Override public void grant(RpcController controller, @@ -1224,7 +1080,23 @@ public class AccessController extends BaseRegionObserver UserPermission perm = ProtobufUtil.toUserPermission(request.getPermission()); AccessControlProtos.GrantResponse response = null; try { - grant(perm); + // verify it's only running at .acl. + if (aclRegion) { + if (LOG.isDebugEnabled()) { + LOG.debug("Received request to grant access permission " + perm.toString()); + } + + requirePermission("grant", perm.getTable(), perm.getFamily(), perm.getQualifier(), Action.ADMIN); + + AccessControlLists.addUserPermission(regionEnv.getConfiguration(), perm); + if (AUDITLOG.isTraceEnabled()) { + // audit log should store permission changes in addition to auth results + AUDITLOG.trace("Granted permission " + perm.toString()); + } + } else { + throw new CoprocessorException(AccessController.class, "This method " + + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); + } response = AccessControlProtos.GrantResponse.getDefaultInstance(); } catch (IOException ioe) { // pass exception back up @@ -1240,7 +1112,24 @@ public class AccessController extends BaseRegionObserver UserPermission perm = ProtobufUtil.toUserPermission(request.getPermission()); AccessControlProtos.RevokeResponse response = null; try { - revoke(perm); + // only allowed to be called on _acl_ region + if (aclRegion) { + if (LOG.isDebugEnabled()) { + LOG.debug("Received request to revoke access permission " + perm.toString()); + } + + requirePermission("revoke", perm.getTable(), perm.getFamily(), + perm.getQualifier(), Action.ADMIN); + + AccessControlLists.removeUserPermission(regionEnv.getConfiguration(), perm); + if (AUDITLOG.isTraceEnabled()) { + // audit log should record all permission changes + AUDITLOG.trace("Revoked permission " + perm.toString()); + } + } else { + throw new CoprocessorException(AccessController.class, "This method " + + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); + } response = AccessControlProtos.RevokeResponse.getDefaultInstance(); } catch (IOException ioe) { // pass exception back up @@ -1256,8 +1145,17 @@ public class AccessController extends BaseRegionObserver byte[] table = request.getTable().toByteArray(); AccessControlProtos.UserPermissionsResponse response = null; try { - List perms = getUserPermissions(table); - response = ResponseConverter.buildUserPermissionsResponse(perms); + // only allowed to be called on _acl_ region + if (aclRegion) { + requirePermission("userPermissions", table, null, null, Action.ADMIN); + + List perms = AccessControlLists.getUserPermissions( + regionEnv.getConfiguration(), table); + response = ResponseConverter.buildUserPermissionsResponse(perms); + } else { + throw new CoprocessorException(AccessController.class, "This method " + + "can only execute at " + Bytes.toString(AccessControlLists.ACL_TABLE_NAME) + " table."); + } } catch (IOException ioe) { // pass exception back up ResponseConverter.setControllerException(controller, ioe); @@ -1269,13 +1167,42 @@ public class AccessController extends BaseRegionObserver public void checkPermissions(RpcController controller, AccessControlProtos.CheckPermissionsRequest request, RpcCallback done) { - Permission[] perms = new Permission[request.getPermissionCount()]; + Permission[] permissions = new Permission[request.getPermissionCount()]; for (int i=0; i < request.getPermissionCount(); i++) { - perms[i] = ProtobufUtil.toPermission(request.getPermission(i)); + permissions[i] = ProtobufUtil.toPermission(request.getPermission(i)); } AccessControlProtos.CheckPermissionsResponse response = null; try { - checkPermissions(perms); + byte[] tableName = regionEnv.getRegion().getTableDesc().getName(); + for (Permission permission : permissions) { + if (permission instanceof TablePermission) { + TablePermission tperm = (TablePermission) permission; + for (Permission.Action action : permission.getActions()) { + if (!Arrays.equals(tperm.getTable(), tableName)) { + throw new CoprocessorException(AccessController.class, String.format("This method " + + "can only execute at the table specified in TablePermission. " + + "Table of the region:%s , requested table:%s", Bytes.toString(tableName), + Bytes.toString(tperm.getTable()))); + } + + HashMap> familyMap = Maps.newHashMapWithExpectedSize(1); + if (tperm.getFamily() != null) { + if (tperm.getQualifier() != null) { + familyMap.put(tperm.getFamily(), Sets.newHashSet(tperm.getQualifier())); + } else { + familyMap.put(tperm.getFamily(), null); + } + } + + requirePermission("checkPermissions", action, regionEnv, familyMap); + } + + } else { + for (Permission.Action action : permission.getActions()) { + requirePermission("checkPermissions", action); + } + } + } response = AccessControlProtos.CheckPermissionsResponse.getDefaultInstance(); } catch (IOException ioe) { ResponseConverter.setControllerException(controller, ioe); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java deleted file mode 100644 index 5d2ce7d3c56..00000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControllerProtocol.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hbase.security.access; - -import java.io.IOException; -import java.util.List; - -import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; - -/** - * A custom protocol defined for maintaining and querying access control lists. - */ -public interface AccessControllerProtocol extends CoprocessorProtocol { - - public static final long VERSION = 1L; - - /** - * Grants the given user or group the privilege to perform the given actions - * @param userPermission the details of the provided user permissions - * @throws IOException if the grant could not be applied - */ - public void grant(UserPermission userPermission) - throws IOException; - - /** - * Grants the given user or group the privilege to perform the given actions - * over the specified scope contained in {@link TablePermission} - * @param user the user name, or, if prefixed with "@", group name receiving - * the grant - * @param permission the details of the provided permissions - * @throws IOException if the grant could not be applied - * @deprecated Use {@link #revoke(UserPermission userPermission)} instead - */ - @Deprecated - public void grant(byte[] user, TablePermission permission) - throws IOException; - - /** - * Revokes a previously granted privilege from a user or group. - * Note that the provided {@link TablePermission} details must exactly match - * a stored grant. For example, if user "bob" has been granted "READ" access - * to table "data", over column family and qualifer "info:colA", then the - * table, column family and column qualifier must all be specified. - * Attempting to revoke permissions over just the "data" table will have - * no effect. - * @param userPermission the details of the previously granted permission to revoke - * @throws IOException if the revocation could not be performed - */ - public void revoke(UserPermission userPermission) - throws IOException; - - /** - * Revokes a previously granted privilege from a user or group. - * Note that the provided {@link TablePermission} details must exactly match - * a stored grant. For example, if user "bob" has been granted "READ" access - * to table "data", over column family and qualifer "info:colA", then the - * table, column family and column qualifier must all be specified. - * Attempting to revoke permissions over just the "data" table will have - * no effect. - * @param user the user name, or, if prefixed with "@", group name whose - * privileges are being revoked - * @param permission the details of the previously granted permission to revoke - * @throws IOException if the revocation could not be performed - * @deprecated Use {@link #revoke(UserPermission userPermission)} instead - */ - @Deprecated - public void revoke(byte[] user, TablePermission permission) - throws IOException; - - /** - * Queries the permissions currently stored for the given table, returning - * a list of currently granted permissions, along with the user or group - * each is associated with. - * @param tableName the table of the permission grants to return - * @return a list of the currently granted permissions, with associated user - * or group names - * @throws IOException if there is an error querying the permissions - */ - public List getUserPermissions(byte[] tableName) - throws IOException; - - /** - * Checks whether the given Permissions will pass the access checks for the - * current user. Global permissions can be checked from the -acl- table - * or any other table, however TablePermissions can only be checked by - * the table's regions. If access control checks fail this method throws - * AccessDeniedException. - * @param permissions to check for. Permission subclasses can be used - * to do more specific checks at the table/family/column level. - * @throws IOException if there is an error checking the permissions - */ - public void checkPermissions(Permission[] permissions) - throws IOException; -} diff --git a/hbase-server/src/main/ruby/hbase/security.rb b/hbase-server/src/main/ruby/hbase/security.rb index e3b99038ba5..2f506a2d5db 100644 --- a/hbase-server/src/main/ruby/hbase/security.rb +++ b/hbase-server/src/main/ruby/hbase/security.rb @@ -40,42 +40,34 @@ module Hbase # Table should exist raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name) - htd = @admin.getTableDescriptor(table_name.to_java_bytes) + tablebytes=table_name.to_java_bytes + htd = @admin.getTableDescriptor(tablebytes) if (family != nil) raise(ArgumentError, "Can't find a family: #{family}") unless htd.hasFamily(family.to_java_bytes) end - # invoke cp endpoint to perform access controlse fambytes = family.to_java_bytes if (family != nil) qualbytes = qualifier.to_java_bytes if (qualifier != nil) - user_permission = org.apache.hadoop.hbase.security.access.UserPermission.new( - user.to_java_bytes, table_name.to_java_bytes, - fambytes, qualbytes, permissions.to_java_bytes) - else - user_permission = org.apache.hadoop.hbase.security.access.UserPermission.new( - user.to_java_bytes, permissions.to_java_bytes) end - meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, - org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) - protocol = meta_table.coprocessorProxy( - org.apache.hadoop.hbase.security.access.AccessControllerProtocol.java_class, - org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) begin - protocol.grant(user_permission) - rescue java.io.IOException => e - if !(e.message.include? "java.lang.NoSuchMethodException") - raise e - end + meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, + org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) + service = meta_table.coprocessorService( + org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) - # Server has not the new API, try the old one - if (table_name == nil) - raise "Global permissions not supported by HBase Server" - end + protocol = org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos:: + AccessControlService.newBlockingStub(service) + perm = org.apache.hadoop.hbase.security.access.Permission.new( + permissions.to_java_bytes) - tp = org.apache.hadoop.hbase.security.access.TablePermission.new(table_name.to_java_bytes, fambytes, qualbytes, permissions.to_java_bytes) - protocol.grant(user.to_java_bytes, tp) + # invoke cp endpoint to perform access controlse + org.apache.hadoop.hbase.protobuf.ProtobufUtil.grant( + protocol, user, tablebytes, fambytes, + qualbytes, perm.getActions()) + ensure + meta_table.close() end end @@ -89,42 +81,31 @@ module Hbase # Table should exist raise(ArgumentError, "Can't find a table: #{table_name}") unless exists?(table_name) - htd = @admin.getTableDescriptor(table_name.to_java_bytes) + tablebytes=table_name.to_java_bytes + htd = @admin.getTableDescriptor(tablebytes) if (family != nil) raise(ArgumentError, "Can't find family: #{family}") unless htd.hasFamily(family.to_java_bytes) end - # invoke cp endpoint to perform access control fambytes = family.to_java_bytes if (family != nil) qualbytes = qualifier.to_java_bytes if (qualifier != nil) - user_permission = org.apache.hadoop.hbase.security.access.UserPermission.new( - user.to_java_bytes, table_name.to_java_bytes, - fambytes, qualbytes, "".to_java_bytes) - else - user_permission = org.apache.hadoop.hbase.security.access.UserPermission.new( - user.to_java_bytes, "".to_java_bytes) end - meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, - org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) - protocol = meta_table.coprocessorProxy( - org.apache.hadoop.hbase.security.access.AccessControllerProtocol.java_class, - org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) begin - protocol.revoke(user_permission) - rescue java.io.IOException => e - if !(e.message.include? "java.lang.NoSuchMethodException") - raise e - end + meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, + org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) + service = meta_table.coprocessorService( + org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) - # Server has not the new API, try the old one - if (table_name == nil) - raise "Global permissions not supported by HBase Server" - end + protocol = org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos:: + AccessControlService.newBlockingStub(service) - tp = org.apache.hadoop.hbase.security.access.TablePermission.new(table_name.to_java_bytes, fambytes, qualbytes, "".to_java_bytes) - protocol.revoke(user.to_java_bytes, tp) + # invoke cp endpoint to perform access controlse + org.apache.hadoop.hbase.protobuf.ProtobufUtil.revoke( + protocol, user, tablebytes, fambytes, qualbytes) + ensure + meta_table.close() end end @@ -134,14 +115,25 @@ module Hbase if (table_name != nil) raise(ArgumentError, "Can't find table: #{table_name}") unless exists?(table_name) + + tablebytes=table_name.to_java_bytes end - meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, - org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) - protocol = meta_table.coprocessorProxy( - org.apache.hadoop.hbase.security.access.AccessControllerProtocol.java_class, - org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) - perms = protocol.getUserPermissions(table_name != nil ? table_name.to_java_bytes : nil) + begin + meta_table = org.apache.hadoop.hbase.client.HTable.new(@config, + org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) + service = meta_table.coprocessorService( + org.apache.hadoop.hbase.HConstants::EMPTY_START_ROW) + + protocol = org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos:: + AccessControlService.newBlockingStub(service) + + # invoke cp endpoint to perform access controlse + perms = org.apache.hadoop.hbase.protobuf.ProtobufUtil.getUserPermissions( + protocol, tablebytes) + ensure + meta_table.close() + end res = {} count = 0 @@ -170,13 +162,10 @@ module Hbase @admin.tableExists(table_name) end - # Make sure that security classes are available + # Make sure that security tables are available def security_available?() - begin - org.apache.hadoop.hbase.security.access.AccessControllerProtocol - rescue NameError - raise(ArgumentError, "DISABLED: Security features are not available in this build of HBase") - end + raise(ArgumentError, "DISABLED: Security features are not available") \ + unless exists?(org.apache.hadoop.hbase.security.access.AccessControlLists::ACL_TABLE_NAME) end end diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessControlFilter.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessControlFilter.java index bd423f18a8c..32f2b757572 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessControlFilter.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessControlFilter.java @@ -38,6 +38,8 @@ import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService; import org.apache.hadoop.hbase.security.AccessDeniedException; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.util.Bytes; @@ -46,6 +48,8 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; +import com.google.protobuf.BlockingRpcChannel; + @Category(LargeTests.class) public class TestAccessControlFilter { private static Log LOG = LogFactory.getLog(TestAccessControlFilter.class); @@ -93,14 +97,14 @@ public class TestAccessControlFilter { public Object run() throws Exception { HTable aclmeta = new HTable(TEST_UTIL.getConfiguration(), AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol acls = aclmeta.coprocessorProxy( - AccessControllerProtocol.class, Bytes.toBytes("testtable")); - UserPermission perm = new UserPermission(Bytes.toBytes(READER.getShortName()), - TABLE, null, Permission.Action.READ); - acls.grant(perm); - perm = new UserPermission(Bytes.toBytes(LIMITED.getShortName()), - TABLE, FAMILY, PUBLIC_COL, Permission.Action.READ); - acls.grant(perm); + byte[] table = Bytes.toBytes("testtable"); + BlockingRpcChannel service = aclmeta.coprocessorService(table); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + ProtobufUtil.grant(protocol, READER.getShortName(), + TABLE, null, null, Permission.Action.READ); + ProtobufUtil.grant(protocol, LIMITED.getShortName(), + TABLE, FAMILY, PUBLIC_COL, Permission.Action.READ); return null; } }); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index c92e371e1e7..c662d55a6de 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -23,6 +23,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.List; import java.util.Map; @@ -53,6 +55,7 @@ import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.RegionServerCoprocessorEnvironment; import org.apache.hadoop.hbase.master.MasterCoprocessorHost; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.protobuf.RequestConverter; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest; @@ -68,7 +71,6 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; -import com.google.common.collect.Lists; import com.google.protobuf.BlockingRpcChannel; import com.google.protobuf.ByteString; import com.google.protobuf.ServiceException; @@ -152,22 +154,22 @@ public class TestAccessController { RCP_ENV = rcpHost.createEnvironment(AccessController.class, ACCESS_CONTROLLER, Coprocessor.PRIORITY_HIGHEST, 1, conf); - protocol.grant(null, newGrantRequest(USER_ADMIN.getShortName(), + protocol.grant(null, RequestConverter.buildGrantRequest(USER_ADMIN.getShortName(), null, null, null, AccessControlProtos.Permission.Action.ADMIN, AccessControlProtos.Permission.Action.CREATE, AccessControlProtos.Permission.Action.READ, AccessControlProtos.Permission.Action.WRITE)); - protocol.grant(null, newGrantRequest(USER_RW.getShortName(), + protocol.grant(null, RequestConverter.buildGrantRequest(USER_RW.getShortName(), TEST_TABLE, TEST_FAMILY, null, AccessControlProtos.Permission.Action.READ, AccessControlProtos.Permission.Action.WRITE)); - protocol.grant(null, newGrantRequest(USER_RO.getShortName(), TEST_TABLE, + protocol.grant(null, RequestConverter.buildGrantRequest(USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null, AccessControlProtos.Permission.Action.READ)); - protocol.grant(null, newGrantRequest(USER_CREATE.getShortName(), + protocol.grant(null, RequestConverter.buildGrantRequest(USER_CREATE.getShortName(), TEST_TABLE, null, null, AccessControlProtos.Permission.Action.CREATE)); } @@ -176,32 +178,6 @@ public class TestAccessController { TEST_UTIL.shutdownMiniCluster(); } - private static AccessControlProtos.GrantRequest newGrantRequest( - String username, byte[] table, byte[] family, byte[] qualifier, - AccessControlProtos.Permission.Action... actions) { - AccessControlProtos.Permission.Builder permissionBuilder = - AccessControlProtos.Permission.newBuilder(); - for (AccessControlProtos.Permission.Action a : actions) { - permissionBuilder.addAction(a); - } - if (table != null) { - permissionBuilder.setTable(ByteString.copyFrom(table)); - } - if (family != null) { - permissionBuilder.setFamily(ByteString.copyFrom(family)); - } - if (qualifier != null) { - permissionBuilder.setQualifier(ByteString.copyFrom(qualifier)); - } - - return AccessControlProtos.GrantRequest.newBuilder() - .setPermission( - AccessControlProtos.UserPermission.newBuilder() - .setUser(ByteString.copyFromUtf8(username)) - .setPermission(permissionBuilder.build()) - ).build(); - } - public void verifyAllowed(User user, PrivilegedExceptionAction... actions) throws Exception { for (PrivilegedExceptionAction action : actions) { try { @@ -243,6 +219,20 @@ public class TestAccessController { if (!isAccessDeniedException) { fail("Not receiving AccessDeniedException for user '" + user.getShortName() + "'"); } + } catch (UndeclaredThrowableException ute) { + // TODO why we get a PrivilegedActionException, which is unexpected? + Throwable ex = ute.getUndeclaredThrowable(); + if (ex instanceof PrivilegedActionException) { + ex = ((PrivilegedActionException) ex).getException(); + } + if (ex instanceof ServiceException) { + ServiceException se = (ServiceException)ex; + if (se.getCause() != null && se.getCause() instanceof AccessDeniedException) { + // expected result + return; + } + } + fail("Not receiving AccessDeniedException for user '" + user.getShortName() + "'"); } catch (AccessDeniedException ade) { // expected result } @@ -706,10 +696,11 @@ public class TestAccessController { PrivilegedExceptionAction grantAction = new PrivilegedExceptionAction() { public Object run() throws Exception { HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - TEST_TABLE); - protocol.grant(new UserPermission(Bytes.toBytes(USER_RO.getShortName()), TEST_TABLE, - TEST_FAMILY, (byte[]) null, Action.READ)); + BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + ProtobufUtil.grant(protocol, USER_RO.getShortName(), TEST_TABLE, + TEST_FAMILY, null, Action.READ); return null; } }; @@ -717,10 +708,11 @@ public class TestAccessController { PrivilegedExceptionAction revokeAction = new PrivilegedExceptionAction() { public Object run() throws Exception { HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - TEST_TABLE); - protocol.revoke(new UserPermission(Bytes.toBytes(USER_RO.getShortName()), TEST_TABLE, - TEST_FAMILY, (byte[]) null, Action.READ)); + BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + ProtobufUtil.revoke(protocol, USER_RO.getShortName(), TEST_TABLE, + TEST_FAMILY, null, Action.READ); return null; } }; @@ -728,9 +720,10 @@ public class TestAccessController { PrivilegedExceptionAction getPermissionsAction = new PrivilegedExceptionAction() { public Object run() throws Exception { HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - TEST_TABLE); - protocol.getUserPermissions(TEST_TABLE); + BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + ProtobufUtil.getUserPermissions(protocol, TEST_TABLE); return null; } }; @@ -771,8 +764,9 @@ public class TestAccessController { // perms only stored against the first region HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - tableName); + BlockingRpcChannel service = acl.coprocessorService(tableName); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); // prepare actions: PrivilegedExceptionAction putActionAll = new PrivilegedExceptionAction() { @@ -870,10 +864,10 @@ public class TestAccessController { verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); // grant table read permission - protocol.grant(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, null, - Permission.Action.READ)); - protocol - .grant(new UserPermission(Bytes.toBytes(gblUser.getShortName()), Permission.Action.READ)); + ProtobufUtil.grant(protocol, tblUser.getShortName(), + tableName, null, null, Permission.Action.READ); + ProtobufUtil.grant(protocol, gblUser.getShortName(), + null, null, null, Permission.Action.READ); Thread.sleep(100); // check @@ -886,10 +880,10 @@ public class TestAccessController { verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); // grant table write permission - protocol.grant(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, null, - Permission.Action.WRITE)); - protocol.grant(new UserPermission(Bytes.toBytes(gblUser.getShortName()), - Permission.Action.WRITE)); + ProtobufUtil.grant(protocol, tblUser.getShortName(), + tableName, null, null, Permission.Action.WRITE); + ProtobufUtil.grant(protocol, gblUser.getShortName(), + null, null, null, Permission.Action.WRITE); Thread.sleep(100); verifyDenied(tblUser, getActionAll, getAction1, getAction2); @@ -901,10 +895,10 @@ public class TestAccessController { verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2); // revoke table permission - protocol.grant(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, null, - Permission.Action.READ, Permission.Action.WRITE)); - protocol.revoke(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, null)); - protocol.revoke(new UserPermission(Bytes.toBytes(gblUser.getShortName()))); + ProtobufUtil.grant(protocol, tblUser.getShortName(), tableName, null, null, + Permission.Action.READ, Permission.Action.WRITE); + ProtobufUtil.revoke(protocol, tblUser.getShortName(), tableName, null, null); + ProtobufUtil.revoke(protocol, gblUser.getShortName(), null, null, null); Thread.sleep(100); verifyDenied(tblUser, getActionAll, getAction1, getAction2); @@ -916,10 +910,10 @@ public class TestAccessController { verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); // grant column family read permission - protocol.grant(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, family1, - Permission.Action.READ)); - protocol - .grant(new UserPermission(Bytes.toBytes(gblUser.getShortName()), Permission.Action.READ)); + ProtobufUtil.grant(protocol, tblUser.getShortName(), + tableName, family1, null, Permission.Action.READ); + ProtobufUtil.grant(protocol, gblUser.getShortName(), + null, null, null, Permission.Action.READ); Thread.sleep(100); @@ -934,10 +928,10 @@ public class TestAccessController { verifyDenied(gblUser, deleteActionAll, deleteAction1, deleteAction2); // grant column family write permission - protocol.grant(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, family2, - Permission.Action.WRITE)); - protocol.grant(new UserPermission(Bytes.toBytes(gblUser.getShortName()), - Permission.Action.WRITE)); + ProtobufUtil.grant(protocol, tblUser.getShortName(), + tableName, family2, null, Permission.Action.WRITE); + ProtobufUtil.grant(protocol, gblUser.getShortName(), + null, null, null, Permission.Action.WRITE); Thread.sleep(100); // READ from family1, WRITE to family2 are allowed @@ -952,8 +946,8 @@ public class TestAccessController { verifyAllowed(gblUser, deleteActionAll, deleteAction1, deleteAction2); // revoke column family permission - protocol.revoke(new UserPermission(Bytes.toBytes(tblUser.getShortName()), tableName, family2)); - protocol.revoke(new UserPermission(Bytes.toBytes(gblUser.getShortName()))); + ProtobufUtil.revoke(protocol, tblUser.getShortName(), tableName, family2, null); + ProtobufUtil.revoke(protocol, gblUser.getShortName(), null, null, null); Thread.sleep(100); @@ -1000,8 +994,9 @@ public class TestAccessController { User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]); HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - tableName); + BlockingRpcChannel service = acl.coprocessorService(tableName); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); PrivilegedExceptionAction getQualifierAction = new PrivilegedExceptionAction() { public Object run() throws Exception { @@ -1032,13 +1027,13 @@ public class TestAccessController { } }; - protocol.revoke(new UserPermission(Bytes.toBytes(user.getShortName()), tableName, family1)); + ProtobufUtil.revoke(protocol, user.getShortName(), tableName, family1, null); verifyDenied(user, getQualifierAction); verifyDenied(user, putQualifierAction); verifyDenied(user, deleteQualifierAction); - protocol.grant(new UserPermission(Bytes.toBytes(user.getShortName()), tableName, family1, - qualifier, Permission.Action.READ)); + ProtobufUtil.grant(protocol, user.getShortName(), + tableName, family1, qualifier, Permission.Action.READ); Thread.sleep(100); verifyAllowed(user, getQualifierAction); @@ -1047,8 +1042,8 @@ public class TestAccessController { // only grant write permission // TODO: comment this portion after HBASE-3583 - protocol.grant(new UserPermission(Bytes.toBytes(user.getShortName()), tableName, family1, - qualifier, Permission.Action.WRITE)); + ProtobufUtil.grant(protocol, user.getShortName(), + tableName, family1, qualifier, Permission.Action.WRITE); Thread.sleep(100); verifyDenied(user, getQualifierAction); @@ -1056,8 +1051,9 @@ public class TestAccessController { verifyAllowed(user, deleteQualifierAction); // grant both read and write permission. - protocol.grant(new UserPermission(Bytes.toBytes(user.getShortName()), tableName, family1, - qualifier, Permission.Action.READ, Permission.Action.WRITE)); + ProtobufUtil.grant(protocol, user.getShortName(), + tableName, family1, qualifier, + Permission.Action.READ, Permission.Action.WRITE); Thread.sleep(100); verifyAllowed(user, getQualifierAction); @@ -1065,8 +1061,8 @@ public class TestAccessController { verifyAllowed(user, deleteQualifierAction); // revoke family level permission won't impact column level. - protocol.revoke(new UserPermission(Bytes.toBytes(user.getShortName()), tableName, family1, - qualifier)); + ProtobufUtil.revoke(protocol, user.getShortName(), + tableName, family1, qualifier); Thread.sleep(100); verifyDenied(user, getQualifierAction); @@ -1084,7 +1080,6 @@ public class TestAccessController { final byte[] family1 = Bytes.toBytes("f1"); final byte[] family2 = Bytes.toBytes("f2"); final byte[] qualifier = Bytes.toBytes("q"); - final byte[] user = Bytes.toBytes("user"); // create table HBaseAdmin admin = TEST_UTIL.getHBaseAdmin(); @@ -1099,49 +1094,54 @@ public class TestAccessController { admin.createTable(htd); HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); - AccessControllerProtocol protocol = acl.coprocessorProxy(AccessControllerProtocol.class, - tableName); + BlockingRpcChannel service = acl.coprocessorService(tableName); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); - List perms = protocol.getUserPermissions(tableName); + List perms = ProtobufUtil.getUserPermissions(protocol, tableName); - UserPermission ownerperm = new UserPermission(Bytes.toBytes(USER_OWNER.getName()), tableName, - null, Action.values()); + UserPermission ownerperm = new UserPermission( + Bytes.toBytes(USER_OWNER.getName()), tableName, null, Action.values()); assertTrue("Owner should have all permissions on table", hasFoundUserPermission(ownerperm, perms)); - UserPermission up = new UserPermission(user, tableName, family1, qualifier, - Permission.Action.READ); + User user = User.createUserForTesting(TEST_UTIL.getConfiguration(), "user", new String[0]); + byte[] userName = Bytes.toBytes(user.getShortName()); + + UserPermission up = new UserPermission(userName, + tableName, family1, qualifier, Permission.Action.READ); assertFalse("User should not be granted permission: " + up.toString(), hasFoundUserPermission(up, perms)); // grant read permission - UserPermission upToSet = new UserPermission(user, tableName, family1, qualifier, - Permission.Action.READ); - protocol.grant(upToSet); - perms = protocol.getUserPermissions(tableName); + ProtobufUtil.grant(protocol, user.getShortName(), + tableName, family1, qualifier, Permission.Action.READ); + perms = ProtobufUtil.getUserPermissions(protocol, tableName); - UserPermission upToVerify = new UserPermission(user, tableName, family1, qualifier, - Permission.Action.READ); + UserPermission upToVerify = new UserPermission( + userName, tableName, family1, qualifier, Permission.Action.READ); assertTrue("User should be granted permission: " + upToVerify.toString(), hasFoundUserPermission(upToVerify, perms)); - upToVerify = new UserPermission(user, tableName, family1, qualifier, Permission.Action.WRITE); + upToVerify = new UserPermission( + userName, tableName, family1, qualifier, Permission.Action.WRITE); assertFalse("User should not be granted permission: " + upToVerify.toString(), hasFoundUserPermission(upToVerify, perms)); // grant read+write - upToSet = new UserPermission(user, tableName, family1, qualifier, Permission.Action.WRITE, - Permission.Action.READ); - protocol.grant(upToSet); - perms = protocol.getUserPermissions(tableName); + ProtobufUtil.grant(protocol, user.getShortName(), + tableName, family1, qualifier, + Permission.Action.WRITE, Permission.Action.READ); + perms = ProtobufUtil.getUserPermissions(protocol, tableName); - upToVerify = new UserPermission(user, tableName, family1, qualifier, Permission.Action.WRITE, - Permission.Action.READ); + upToVerify = new UserPermission(userName, tableName, family1, + qualifier, Permission.Action.WRITE, Permission.Action.READ); assertTrue("User should be granted permission: " + upToVerify.toString(), hasFoundUserPermission(upToVerify, perms)); - protocol.revoke(upToSet); - perms = protocol.getUserPermissions(tableName); + ProtobufUtil.revoke(protocol, user.getShortName(), tableName, family1, qualifier, + Permission.Action.WRITE, Permission.Action.READ); + perms = ProtobufUtil.getUserPermissions(protocol, tableName); assertFalse("User should not be granted permission: " + upToVerify.toString(), hasFoundUserPermission(upToVerify, perms)); @@ -1151,9 +1151,9 @@ public class TestAccessController { User newOwner = User.createUserForTesting(conf, "new_owner", new String[] {}); htd.setOwner(newOwner); admin.modifyTable(tableName, htd); - perms = protocol.getUserPermissions(tableName); - UserPermission newOwnerperm = new UserPermission(Bytes.toBytes(newOwner.getName()), tableName, - null, Action.values()); + perms = ProtobufUtil.getUserPermissions(protocol, tableName); + UserPermission newOwnerperm = new UserPermission( + Bytes.toBytes(newOwner.getName()), tableName, null, Action.values()); assertTrue("New owner should have all permissions on table", hasFoundUserPermission(newOwnerperm, perms)); @@ -1216,20 +1216,6 @@ public class TestAccessController { } } - public void grant(AccessControlService.BlockingInterface protocol, User user, - byte[] t, byte[] f, byte[] q, Permission.Action... actions) - throws ServiceException { - List permActions = - Lists.newArrayListWithCapacity(actions.length); - for (Action a : actions) { - permActions.add(ProtobufUtil.toPermissionAction(a)); - } - AccessControlProtos.GrantRequest request = - newGrantRequest(user.getShortName(), t, f, q, permActions.toArray( - new AccessControlProtos.Permission.Action[actions.length])); - protocol.grant(null, request); - } - @Test public void testCheckPermissions() throws Exception { final HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME); @@ -1270,9 +1256,12 @@ public class TestAccessController { User userColumn = User.createUserForTesting(conf, "user_check_perms_family", new String[0]); User userQualifier = User.createUserForTesting(conf, "user_check_perms_q", new String[0]); - grant(protocol, userTable, TEST_TABLE, null, null, Permission.Action.READ); - grant(protocol, userColumn, TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ); - grant(protocol, userQualifier, TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ); + ProtobufUtil.grant(protocol, userTable.getShortName(), + TEST_TABLE, null, null, Permission.Action.READ); + ProtobufUtil.grant(protocol, userColumn.getShortName(), + TEST_TABLE, TEST_FAMILY, null, Permission.Action.READ); + ProtobufUtil.grant(protocol, userQualifier.getShortName(), + TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ); PrivilegedExceptionAction tableRead = new PrivilegedExceptionAction() { @Override