[ 
https://issues.apache.org/jira/browse/HBASE-28984?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on HBASE-28984 started by Peiming Wu.
------------------------------------------
> 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
>
> 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)

Reply via email to