This is an automated email from the ASF dual-hosted git repository. dineshkumar-yadav pushed a commit to branch sandbox/dineshkumar-yadav/RANGER-5750 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 42b248fabaa4397bee1b266c7b8f1e02462ea235 Author: Ramesh Mani <[email protected]> AuthorDate: Wed Sep 16 22:33:20 2026 -0700 RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin Co-authored-by: Ramesh Mani <[email protected]> Co-authored-by: Cursor <[email protected]> --- .../hbase/RangerAuthorizationCoprocessor.java | 35 +++++++++++++++++--- .../hbase/RangerAuthorizationCoprocessorTest.java | 38 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 5 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 a3ddd885d..c1fe05a26 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 @@ -126,14 +126,32 @@ 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(Configuration conf, ObserverContext<?> ctx) throws IOException { User user = User.getCurrent(); if (user == null) { 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); - 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."); } } @@ -743,7 +761,7 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin String message = "Unexpeceted: User is null: access denied, not audited!"; LOG.warn("canSkipAccessCheck: exiting" + message); 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; } else { @@ -779,9 +797,16 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin return false; } - 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; } return false; 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 f982910ee..6cd778084 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 @@ -19,10 +19,15 @@ package org.apache.ranger.authorization.hbase; import static org.junit.Assert.*; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import java.lang.reflect.Field; import java.util.Map; import java.util.Set; +import org.apache.hadoop.hbase.security.User; import org.junit.Test; public class RangerAuthorizationCoprocessorTest { @@ -48,4 +53,37 @@ public void test_getColumnFamilies_firewalling() { // same for passing in an empty collection // result = _coprocessor.getColumnFamilies(new HashMap<byte[], ? extends Collection<?>>()); } + + @Test + public void test_isSpecialTable_and_metadataRead() throws Exception { + RangerAuthorizationCoprocessor cp = new RangerAuthorizationCoprocessor(); + assertTrue(cp.isSpecialTable("hbase:meta")); + assertFalse(cp.isSpecialTable("normal")); + assertFalse(cp.isAccessForMetadataRead("read", "hbase:acl", null)); + 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()); + 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); + 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); + assertFalse(cp.isAccessForMetadataRead("read", "hbase:acl", normalUser)); + + // Test for normal user on hbase:meta (should be allowed) + assertTrue(cp.isAccessForMetadataRead("read", "hbase:meta", normalUser)); + } }
