[
https://issues.apache.org/jira/browse/HBASE-28984?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Duo Zhang resolved HBASE-28984.
-------------------------------
Fix Version/s: 2.6.3
2.5.12
2.7.0
3.0.0-beta-2
Hadoop Flags: Reviewed
Resolution: Fixed
Pushed to all active branches.
Thanks [~peiming.wu] for contributing!
> Alter table causes AccessDeniedException at the client side
> -----------------------------------------------------------
>
> Key: HBASE-28984
> URL: https://issues.apache.org/jira/browse/HBASE-28984
> Project: HBase
> Issue Type: Bug
> Affects Versions: 2.4.16
> Reporter: Peiming Wu
> Assignee: Peiming Wu
> Priority: Major
> Labels: pull-request-available
> Fix For: 2.7.0, 3.0.0-beta-2, 2.6.3, 2.5.12
>
>
> When altering a table there is a chance that the client catches some
> AccessDeniedExceptions:
>
>
> {code:java}
> #444021290, table=***, attempt=1/5 failed=1ops, last exception:
> org.apache.hadoop.hbase.security.AccessDeniedException:
> org.apache.hadoop.hbase.security.AccessDeniedException: Insufficient
> permissions (user=***, scope=default:***, family=***,
> params=[table=***,family=***],action=WRITE)
> at
> org.apache.hadoop.hbase.security.access.AccessController.prePut(AccessController.java:1388)
> at
> org.apache.hadoop.hbase.coprocessor.RegionObserver.prePut(RegionObserver.java:413)
> at
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost$23.call(RegionCoprocessorHost.java:907)
> at
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost$23.call(RegionCoprocessorHost.java:904)
> at
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost$ObserverOperationWithoutResult.callObserver(CoprocessorHost.java:558)
> at
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost.execOperation(CoprocessorHost.java:631)
> at
> org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost.prePut(RegionCoprocessorHost.java:904)
> at
> org.apache.hadoop.hbase.regionserver.HRegion$MutationBatchOperation.callPreMutateCPHook(HRegion.java:4160)
> at
> org.apache.hadoop.hbase.regionserver.HRegion$MutationBatchOperation.access$800(HRegion.java:3610)
> at
> org.apache.hadoop.hbase.regionserver.HRegion$MutationBatchOperation$1.visit(HRegion.java:3685)
> at
> org.apache.hadoop.hbase.regionserver.HRegion$BatchOperation.visitBatchOperations(HRegion.java:3218)
> at
> org.apache.hadoop.hbase.regionserver.HRegion$MutationBatchOperation.checkAndPrepare(HRegion.java:3674)
> at
> org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:4447)
> at
> org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:4380)
> at
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doBatchOp(RSRpcServices.java:1009)
> at
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicBatchOp(RSRpcServices.java:927)
> at
> org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicRegionMutation(RSRpcServices.java:892)
> at
> org.apache.hadoop.hbase.regionserver.RSRpcServices.multi(RSRpcServices.java:2855)
> at
> org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:45008)
> at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:387)
> at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:132)
> at
> org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:369)
> at
> org.apache.hadoop.hbase.ipc.RpcExecutor$Handler.run(RpcExecutor.java:349)
> {code}
>
>
> This is because HBase updates the table owner when a table is altered. By
> updating the table, ZKPermissionWatcher receives the permission changes and
> tries to update the permission cache in AuthManager:
>
> [https://github.com/apache/hbase/blob/rel/2.4.16/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AuthManager.java#L185-L192]
> {code:java}
> private void updateTableCache(TableName table, ListMultimap<String,
> Permission> tablePerms) {
> PermissionCache<TablePermission> cacheToUpdate =
> tableCache.getOrDefault(table, new PermissionCache<>());
> clearCache(cacheToUpdate);
> updateCache(tablePerms, cacheToUpdate);
> tableCache.put(table, cacheToUpdate);
> mtime.incrementAndGet();
> } {code}
>
> At the same time, AccessController is accessing the same reference of the
> permission cache in AuthManager:
> [https://github.com/apache/hbase/blob/rel/2.4.16/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AuthManager.java#L298-L319]
> {code:java}
> public boolean accessUserTable(User user, TableName table,
> Permission.Action action) {
> if (user == null) {
> return false;
> }
> if (table == null) {
> table = PermissionStorage.ACL_TABLE_NAME;
> }
> if (authorizeUserNamespace(user, table.getNamespaceAsString(), action)) {
> return true;
> }
> PermissionCache<TablePermission> tblPermissions =
> tableCache.getOrDefault(table, TBL_NO_PERMISSION);
> if (hasAccessTable(tblPermissions.get(user.getShortName()), action)) {
> return true;
> }
> for (String group : user.getGroupNames()) {
> if (hasAccessTable(tblPermissions.get(AuthUtil.toGroupEntry(group)),
> action)) {
> return true;
> }
> }
> return false;
> } {code}
>
> I think this is a bug introduced in the previous refactoring:
> https://issues.apache.org/jira/browse/HBASE-21255
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)