You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by rm...@apache.org on 2026/09/17 05:33:26 UTC

(ranger) branch master updated: RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin (#1201)

This is an automated email from the ASF dual-hosted git repository.

rameeshm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 191548874 RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin (#1201)
191548874 is described below

commit 191548874d992f6db1c0c531a4d2426bc96c7628
Author: Ramesh Mani <rm...@cloudera.com>
AuthorDate: Wed Sep 16 22:33:20 2026 -0700

    RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin (#1201)
    
    * RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin
    
    * RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin - review comments addressed
    
    * RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin - review comments set#2 addressed
    
    ---------
    
    Co-authored-by: Ramesh Mani <rm...@apache.org>
---
 .../hbase/RangerAuthorizationCoprocessor.java      | 35 ++++++++++++++++++----
 .../hbase/RangerAuthorizationCoprocessorTest.java  | 30 +++++++++++++++++--
 2 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
index ffd642613..2f55260ea 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessor.java
@@ -852,6 +852,24 @@ protected byte[] getTableName(RegionCoprocessorEnvironment e) {
         return tableName;
     }
 
+    private boolean isSystemOrSuperUser(User activeUser) {
+        if (activeUser == null) {
+            return false;
+        }
+        if (userUtils.isSuperUser(activeUser)) {
+            return true;
+        }
+        try {
+            User currentUser = User.getCurrent();
+            if (currentUser != null) {
+                return Objects.equals(currentUser.getShortName(), activeUser.getShortName());
+            }
+        } catch (IOException e) {
+            LOG.warn("Unable to obtain the current user", e);
+        }
+        return false;
+    }
+
     protected void requireSystemOrSuperUser(ObserverContext<?> ctx) throws IOException {
         User user = User.getCurrent();
 
@@ -859,10 +877,9 @@ protected void requireSystemOrSuperUser(ObserverContext<?> ctx) throws IOExcepti
             throw new IOException("Unable to obtain the current user, authorization checks for internal operations will not work correctly!");
         }
 
-        String systemUser = user.getShortName();
-        User   activeUser = getActiveUser(ctx);
+        User activeUser = getActiveUser(ctx);
 
-        if (!Objects.equals(systemUser, activeUser.getShortName()) && !userUtils.isSuperUser(activeUser)) {
+        if (activeUser == null || !isSystemOrSuperUser(activeUser)) {
             throw new AccessDeniedException("User '" + user.getShortName() + "is not system or super user.");
         }
     }
@@ -1390,7 +1407,7 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin
             LOG.warn("canSkipAccessCheck: exiting{}", "Unexpeceted: User is null: access denied, not audited!");
 
             throw new AccessDeniedException("No user associated with request (" + operation + ") for action: " + access + "on table:" + table);
-        } else if (isAccessForMetadataRead(access, table)) {
+        } else if (isAccessForMetadataRead(access, table, user)) {
             LOG.debug("canSkipAccessCheck: true: metadata read access always allowed, not audited");
 
             result = true;
@@ -1434,9 +1451,15 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin
 
     /* ---- EndpointObserver implementation ---- */
 
-    boolean isAccessForMetadataRead(String access, String table) {
+    boolean isAccessForMetadataRead(String access, String table, User user) {
         if (authUtils.isReadAccess(access) && isSpecialTable(table)) {
-            LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed!");
+            if (StringUtils.equals(table, "hbase:acl")) {
+                if (!isSystemOrSuperUser(user)) {
+                    LOG.debug("isAccessForMetadataRead: Metadata tables read: not access allowed for user: {}!", (user != null ? user.getShortName() : ""));
+                    return false;
+                }
+            }
+            LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed for user: {}!", (user != null ? user.getShortName() : ""));
 
             return true;
         }
diff --git a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessorTest.java b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessorTest.java
index 340ac1849..481921ecd 100644
--- a/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessorTest.java
+++ b/hbase-agent/src/test/java/org/apache/ranger/authorization/hbase/RangerAuthorizationCoprocessorTest.java
@@ -391,12 +391,36 @@ public void test18_requirePermission_region_allowsOrDenies() throws Exception {
     }
 
     @Test
-    public void test19_isSpecialTable_and_metadataRead() {
+    public void test19_isSpecialTable_and_metadataRead() throws Exception {
         RangerAuthorizationCoprocessor cp = new RangerAuthorizationCoprocessor();
         Assertions.assertTrue(cp.isSpecialTable("hbase:meta"));
         Assertions.assertFalse(cp.isSpecialTable("normal"));
-        Assertions.assertTrue(cp.isAccessForMetadataRead("read", "hbase:acl"));
-        Assertions.assertFalse(cp.isAccessForMetadataRead("write", "hbase:acl"));
+        Assertions.assertFalse(cp.isAccessForMetadataRead("read", "hbase:acl", null));
+        Assertions.assertFalse(cp.isAccessForMetadataRead("write", "hbase:acl", null));
+
+        // Test for system user bypass on hbase:acl
+        User systemUser = mock(User.class);
+        when(systemUser.getShortName()).thenReturn(User.getCurrent().getShortName());
+        Assertions.assertTrue(cp.isAccessForMetadataRead("read", "hbase:acl", systemUser));
+
+        // Test for super user bypass on hbase:acl
+        User superUser = mock(User.class);
+        when(superUser.getShortName()).thenReturn("some_super_user");
+        HbaseUserUtils userUtils = mock(HbaseUserUtils.class);
+        lenient().when(userUtils.isSuperUser(superUser)).thenReturn(true);
+        Field userUtilsField = RangerAuthorizationCoprocessor.class.getDeclaredField("userUtils");
+        userUtilsField.setAccessible(true);
+        userUtilsField.set(cp, userUtils);
+        Assertions.assertTrue(cp.isAccessForMetadataRead("read", "hbase:acl", superUser));
+
+        // Test for normal user on hbase:acl (should be denied)
+        User normalUser = mock(User.class);
+        when(normalUser.getShortName()).thenReturn("normal_user");
+        lenient().when(userUtils.isSuperUser(normalUser)).thenReturn(false);
+        Assertions.assertFalse(cp.isAccessForMetadataRead("read", "hbase:acl", normalUser));
+
+        // Test for normal user on hbase:meta (should be allowed)
+        Assertions.assertTrue(cp.isAccessForMetadataRead("read", "hbase:meta", normalUser));
     }
 
     @Test