Peiming Wu created HBASE-28984:
----------------------------------
Summary: 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
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)