From d2c1fa8f93dc1f72487a85d2128b948a035095e4 Mon Sep 17 00:00:00 2001 From: Ramesh Mani Date: Mon, 31 Aug 2026 16:14:36 -0700 Subject: [PATCH 1/3] RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin --- .../hbase/RangerAuthorizationCoprocessor.java | 21 +++++++++++++++++-- .../RangerAuthorizationCoprocessorTest.java | 21 ++++++++++++++++--- 2 files changed, 37 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 ffd642613a..59698427e4 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 @@ -1390,7 +1390,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,8 +1434,25 @@ 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)) { + if (StringUtils.equals(table, "hbase:acl")) { + boolean isSystemOrSuperUser = false; + try { + User currentUser = User.getCurrent(); + if (currentUser != null && user != null) { + isSystemOrSuperUser = Objects.equals(currentUser.getShortName(), user.getShortName()); + } + } catch (IOException e) { + LOG.warn("Unable to obtain the current user", e); + } + if (!isSystemOrSuperUser && user != null) { + isSystemOrSuperUser = userUtils.isSuperUser(user); + } + if (!isSystemOrSuperUser) { + return false; + } + } LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed!"); 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 340ac18492..1ce4773484 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,27 @@ 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 From 2ff0047bde2c453f26347a74d53ff5b82f73a1f7 Mon Sep 17 00:00:00 2001 From: Ramesh Mani Date: Mon, 14 Sep 2026 12:30:11 -0700 Subject: [PATCH 2/3] RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin - review comments addressed --- .../hbase/RangerAuthorizationCoprocessor.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 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 59698427e4..8a69c01770 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 @@ -1437,27 +1437,31 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin boolean isAccessForMetadataRead(String access, String table, User user) { if (authUtils.isReadAccess(access) && isSpecialTable(table)) { if (StringUtils.equals(table, "hbase:acl")) { - boolean isSystemOrSuperUser = false; - try { - User currentUser = User.getCurrent(); - if (currentUser != null && user != null) { - isSystemOrSuperUser = Objects.equals(currentUser.getShortName(), user.getShortName()); - } - } catch (IOException e) { - LOG.warn("Unable to obtain the current user", e); + if (user == null) { + return false; } - if (!isSystemOrSuperUser && user != null) { - isSystemOrSuperUser = userUtils.isSuperUser(user); + boolean isSystemOrSuperUser = userUtils.isSuperUser(user); + if (!isSystemOrSuperUser) { + try { + User currentUser = User.getCurrent(); + if (currentUser != null) { + isSystemOrSuperUser = Objects.equals(currentUser.getShortName(), user.getShortName()); + } + } catch (IOException e) { + LOG.warn("Unable to obtain the current user", e); + } } if (!isSystemOrSuperUser) { return false; } } - LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed!"); + LOG.debug("isAccessForMetadataRead: Metadata tables read: access allowed for user: {}!", (user != null ? user.getShortName() : "")); return true; } + LOG.debug("isAccessForMetadataRead: Metadata tables read: not access allowed for user: {}!", (user != null ? user.getShortName() : "")); + return false; } From be06378df3c8fe8bb5a2c6ed17ef25dc84fa5f06 Mon Sep 17 00:00:00 2001 From: Ramesh Mani Date: Wed, 16 Sep 2026 09:24:34 -0700 Subject: [PATCH 3/3] RANGER-5750:Handle authorization of hbase:acl table in RangerAuthorizationCoprocessor in HBase Ranger plugin - review comments set#2 addressed --- .../hbase/RangerAuthorizationCoprocessor.java | 42 ++++++++++--------- .../RangerAuthorizationCoprocessorTest.java | 9 ++++ 2 files changed, 31 insertions(+), 20 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 8a69c01770..2f55260ea5 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."); } } @@ -1437,21 +1454,8 @@ boolean canSkipAccessCheck(User user, final String operation, String access, fin boolean isAccessForMetadataRead(String access, String table, User user) { if (authUtils.isReadAccess(access) && isSpecialTable(table)) { if (StringUtils.equals(table, "hbase:acl")) { - if (user == null) { - return false; - } - boolean isSystemOrSuperUser = userUtils.isSuperUser(user); - if (!isSystemOrSuperUser) { - try { - User currentUser = User.getCurrent(); - if (currentUser != null) { - isSystemOrSuperUser = Objects.equals(currentUser.getShortName(), user.getShortName()); - } - } catch (IOException e) { - LOG.warn("Unable to obtain the current user", e); - } - } - if (!isSystemOrSuperUser) { + if (!isSystemOrSuperUser(user)) { + LOG.debug("isAccessForMetadataRead: Metadata tables read: not access allowed for user: {}!", (user != null ? user.getShortName() : "")); return false; } } @@ -1460,8 +1464,6 @@ boolean isAccessForMetadataRead(String access, String table, User user) { return true; } - LOG.debug("isAccessForMetadataRead: Metadata tables read: not access allowed for user: {}!", (user != null ? user.getShortName() : "")); - 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 1ce4773484..481921ecd8 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 @@ -412,6 +412,15 @@ public void test19_isSpecialTable_and_metadataRead() throws Exception { 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