This is an automated email from the ASF dual-hosted git repository. dineshkumar-yadav pushed a commit to branch sandbox/dineshkumar-yadav/ranger-2.10-RANGER-5824 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 9fb53d6751d70d1d1561b53583268de8ef75500f Author: Dineshkumar Yadav <[email protected]> AuthorDate: Thu Oct 8 12:53:52 2026 +0530 RANGER-5824: Align Sqoop Ranger authorizer with other plugins --- .../sqoop/authorizer/RangerSqoopAuthorizer.java | 31 +++-- .../RangerSqoopAuthorizerFailClosedTest.java | 137 +++++++++++++++++++++ 2 files changed, 159 insertions(+), 9 deletions(-) diff --git a/plugin-sqoop/src/main/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizer.java b/plugin-sqoop/src/main/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizer.java index 6557c8902..5ea75fcfa 100644 --- a/plugin-sqoop/src/main/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizer.java +++ b/plugin-sqoop/src/main/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizer.java @@ -101,15 +101,28 @@ public void checkPrivileges(MPrincipal principal, List<MPrivilege> privileges) t RangerSqoopPlugin plugin = sqoopPlugin; - if (plugin != null) { - for (MPrivilege privilege : privileges) { - RangerSqoopAccessRequest request = new RangerSqoopAccessRequest(principal, privilege, clientIPAddress); - - RangerAccessResult result = plugin.isAccessAllowed(request); - if (result != null && !result.getIsAllowed()) { - throw new SqoopException(SecurityError.AUTH_0014, "principal=" + principal - + " does not have privileges for : " + privilege); - } + if (plugin == null) { + LOG.error("Ranger Sqoop plugin is not initialized; denying access for principal={}", principal); + + throw new SqoopException(SecurityError.AUTH_0014, "Ranger authorization plugin is not initialized"); + } + + for (MPrivilege privilege : privileges) { + RangerSqoopAccessRequest request = new RangerSqoopAccessRequest(principal, privilege, clientIPAddress); + + RangerAccessResult result = plugin.isAccessAllowed(request); + + if (result == null) { + LOG.error("Ranger plugin returned null for request={}; denying access for principal={}", request, + principal); + + throw new SqoopException(SecurityError.AUTH_0014, "principal=" + principal + + " does not have privileges for : " + privilege); + } + + if (!result.getIsAllowed()) { + throw new SqoopException(SecurityError.AUTH_0014, "principal=" + principal + + " does not have privileges for : " + privilege); } } diff --git a/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerFailClosedTest.java b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerFailClosedTest.java new file mode 100644 index 000000000..f04c7044e --- /dev/null +++ b/plugin-sqoop/src/test/java/org/apache/ranger/authorization/sqoop/authorizer/RangerSqoopAuthorizerFailClosedTest.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ranger.authorization.sqoop.authorizer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.List; + +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.MPrincipal; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Verifies authorization when the Ranger plugin is unavailable or returns no decision. + */ +public class RangerSqoopAuthorizerFailClosedTest { + private static final String TEST_USER = "test-user"; + + private RangerSqoopAuthorizer authorizer; + + private RangerSqoopPlugin sqoopPluginBefore; + + @Before + public void setUp() throws Exception { + sqoopPluginBefore = (RangerSqoopPlugin) getSqoopPluginField().get(null); + authorizer = new RangerSqoopAuthorizer(); + } + + @After + public void tearDown() throws Exception { + getSqoopPluginField().set(null, sqoopPluginBefore); + } + + @Test(expected = SqoopException.class) + public void checkPrivilegesDeniesWhenPluginReturnsNull() throws Exception { + RangerSqoopPlugin plugin = mock(RangerSqoopPlugin.class); + + when(plugin.isAccessAllowed(any(RangerAccessRequest.class))).thenReturn(null); + + setSqoopPlugin(plugin); + + authorizer.checkPrivileges(buildUserPrincipal(), buildReadConnectorPrivilege()); + } + + @Test(expected = SqoopException.class) + public void checkPrivilegesDeniesWhenPluginIsNull() throws Exception { + setSqoopPlugin(null); + + authorizer.checkPrivileges(buildUserPrincipal(), buildReadConnectorPrivilege()); + } + + @Test(expected = SqoopException.class) + public void checkPrivilegesDeniesWhenPluginReturnsNotAllowed() throws Exception { + RangerSqoopPlugin plugin = mock(RangerSqoopPlugin.class); + RangerAccessResult result = mock(RangerAccessResult.class); + + when(result.getIsAllowed()).thenReturn(false); + when(plugin.isAccessAllowed(any(RangerAccessRequest.class))).thenReturn(result); + + setSqoopPlugin(plugin); + + authorizer.checkPrivileges(buildUserPrincipal(), buildReadConnectorPrivilege()); + } + + @Test + public void checkPrivilegesAllowsWhenPluginReturnsAllowed() throws Exception { + RangerSqoopPlugin plugin = mock(RangerSqoopPlugin.class); + RangerAccessResult result = mock(RangerAccessResult.class); + + when(result.getIsAllowed()).thenReturn(true); + when(plugin.isAccessAllowed(any(RangerAccessRequest.class))).thenReturn(result); + + setSqoopPlugin(plugin); + + authorizer.checkPrivileges(buildUserPrincipal(), buildReadConnectorPrivilege()); + } + + private static Field getSqoopPluginField() throws NoSuchFieldException { + Field field = RangerSqoopAuthorizer.class.getDeclaredField("sqoopPlugin"); + + field.setAccessible(true); + + return field; + } + + private static void setSqoopPlugin(RangerSqoopPlugin plugin) throws Exception { + getSqoopPluginField().set(null, plugin); + } + + private static MPrincipal buildUserPrincipal() { + MPrincipal principal = mock(MPrincipal.class); + + when(principal.getType()).thenReturn(MPrincipal.TYPE.USER.name()); + when(principal.getName()).thenReturn(TEST_USER); + + return principal; + } + + private static List<MPrivilege> buildReadConnectorPrivilege() { + MResource resource = mock(MResource.class); + + when(resource.getType()).thenReturn(MResource.TYPE.CONNECTOR.name()); + when(resource.getName()).thenReturn("hdfs-connector"); + + MPrivilege privilege = mock(MPrivilege.class); + + when(privilege.getResource()).thenReturn(resource); + when(privilege.getAction()).thenReturn("read"); + + return Collections.singletonList(privilege); + } +}
