This is an automated email from the ASF dual-hosted git repository.
dhavalshah9131 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 c1fe2be4c RANGER-5351:Test Cases for agents-cred [ranger-plugins-cred]
Module (#745)
c1fe2be4c is described below
commit c1fe2be4c8762543608beefa42a493437000b1b0
Author: Bhaavesh Amol Amre <[email protected]>
AuthorDate: Fri Nov 28 18:33:52 2025 +0530
RANGER-5351:Test Cases for agents-cred [ranger-plugins-cred] Module (#745)
---
agents-cred/pom.xml | 12 ++
.../credutils/CredentialsProviderUtilTest.java | 218 +++++++++++++++++++++
.../kerberos/KerberosCredentialsProviderTest.java | 86 ++++++++
.../credutils/kerberos/KeytabJaasConfTest.java | 73 +++++++
.../hadoop/utils/RangerCredentialProviderTest.java | 16 +-
5 files changed, 404 insertions(+), 1 deletion(-)
diff --git a/agents-cred/pom.xml b/agents-cred/pom.xml
index 362a4e9a9..6c181734e 100644
--- a/agents-cred/pom.xml
+++ b/agents-cred/pom.xml
@@ -118,6 +118,18 @@
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-inline</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
diff --git
a/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/CredentialsProviderUtilTest.java
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/CredentialsProviderUtilTest.java
new file mode 100644
index 000000000..b35545f92
--- /dev/null
+++
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/CredentialsProviderUtilTest.java
@@ -0,0 +1,218 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.credutils;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for CredentialsProviderUtil
+ */
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class CredentialsProviderUtilTest {
+ private MockedStatic<GSSManager> gssManagerStatic;
+ private MockedStatic<AccessController> accessControllerStatic;
+
+ @BeforeEach
+ public void setup() {
+ CredentialsProviderUtil.ticketExpireTime80 = 0L;
+ }
+
+ @AfterEach
+ public void tearDown() {
+ if (gssManagerStatic != null) {
+ gssManagerStatic.close();
+ }
+ if (accessControllerStatic != null) {
+ accessControllerStatic.close();
+ }
+ }
+
+ @Test
+ public void getBasicCredentials_setsUsernamePasswordOnAnyScope() {
+ CredentialsProvider provider =
CredentialsProviderUtil.getBasicCredentials("user", "pass");
+ Credentials creds = provider.getCredentials(AuthScope.ANY);
+ assertNotNull(creds);
+ assertInstanceOf(UsernamePasswordCredentials.class, creds);
+ UsernamePasswordCredentials upc = (UsernamePasswordCredentials) creds;
+ assertEquals("user", upc.getUserName());
+ assertEquals("pass", upc.getPassword());
+ }
+
+ @Test
+ public void getKerberosCredentials_wrapsGssException() throws Exception {
+ GSSManager mockManager = mock(GSSManager.class);
+ gssManagerStatic = mockStatic(GSSManager.class);
+ gssManagerStatic.when(GSSManager::getInstance).thenReturn(mockManager);
+ when(mockManager.createName(anyString(), any())).thenThrow(new
GSSException(GSSException.FAILURE));
+ RuntimeException ex = assertThrows(RuntimeException.class, () ->
CredentialsProviderUtil.getKerberosCredentials("user", "pw"));
+ assertNotNull(ex.getCause());
+ }
+
+ @Test
+ public void getKerberosCredentials_wrapsPrivilegedActionException() throws
Exception {
+ GSSManager mockManager = mock(GSSManager.class);
+ gssManagerStatic = mockStatic(GSSManager.class);
+ gssManagerStatic.when(GSSManager::getInstance).thenReturn(mockManager);
+ GSSName mockName = mock(GSSName.class);
+ when(mockManager.createName(eq("[email protected]"),
eq(GSSName.NT_USER_NAME))).thenReturn(mockName);
+ when(mockManager.createCredential(eq(mockName),
eq(GSSCredential.DEFAULT_LIFETIME), any(Oid.class),
eq(GSSCredential.INITIATE_ONLY))).thenThrow(new
GSSException(GSSException.FAILURE));
+
+ try (MockedStatic<CredentialsProviderUtil> cpu =
mockStatic(CredentialsProviderUtil.class, CALLS_REAL_METHODS)) {
+ Subject subject = new Subject();
+ cpu.when(() ->
CredentialsProviderUtil.login(eq("[email protected]"),
eq("/tmp/keytab"))).thenReturn(subject);
+
+ RuntimeException ex = assertThrows(RuntimeException.class, () ->
CredentialsProviderUtil.getKerberosCredentials("[email protected]",
"/tmp/keytab"));
+ assertInstanceOf(PrivilegedActionException.class, ex.getCause());
+ }
+ }
+
+ @Test
+ public void doAsPrivilegedWrapper_unwrapsNestedPrivilegedActionException()
throws Exception {
+ Subject subject = new Subject();
+ PrivilegedActionException inner = new
PrivilegedActionException(new Exception("root"));
+ PrivilegedExceptionAction<Object> action = () -> {
+ throw inner;
+ };
+ PrivilegedActionException thrown =
assertThrows(PrivilegedActionException.class, () ->
CredentialsProviderUtil.doAsPrivilegedWrapper(subject, action,
mock(AccessControlContext.class)));
+ assertInstanceOf(PrivilegedActionException.class, thrown.getCause());
+ assertInstanceOf(Exception.class, thrown.getCause().getCause());
+ assertEquals("root", thrown.getCause().getCause().getMessage());
+ }
+
+ @Test
+ public void getTGT_returnsTicketMatchingTgtPattern() {
+ Subject subject = new Subject();
+ KerberosPrincipal client = new KerberosPrincipal("[email protected]");
+ KerberosPrincipal server = new
KerberosPrincipal("krbtgt/[email protected]");
+ Date now = new Date();
+ Date end = new Date(System.currentTimeMillis() +
60_000);
+ Date renew = new Date(end.getTime() + 60_000);
+ KerberosTicket tgt = new KerberosTicket(new byte[] {1}, client,
server, new byte[] {1}, 1, null, now, now, end, renew, null);
+ subject.getPrivateCredentials().add(tgt);
+
+ KerberosTicket found = CredentialsProviderUtil.getTGT(subject);
+ assertNotNull(found);
+ assertEquals(server, found.getServer());
+ }
+
+ @Test
+ public void ticketWillExpire_computes80PercentThresholdAndResets() {
+ KerberosPrincipal client = new KerberosPrincipal("[email protected]");
+ KerberosPrincipal server = new
KerberosPrincipal("krbtgt/[email protected]");
+ Date start = new Date(System.currentTimeMillis() - 1000);
+ Date end = new Date(System.currentTimeMillis() +
10_000);
+ Date renew = new Date(end.getTime() + 10_000);
+ KerberosTicket ticket = new KerberosTicket(new byte[] {1}, client,
server, new byte[] {1}, 1, null, start, start, end, renew, null);
+
+ Boolean first = CredentialsProviderUtil.ticketWillExpire(ticket);
+ assertFalse(first);
+ CredentialsProviderUtil.ticketExpireTime80 =
System.currentTimeMillis() - 1;
+ Boolean second = CredentialsProviderUtil.ticketWillExpire(ticket);
+ assertTrue(second);
+ assertEquals(0L, CredentialsProviderUtil.ticketExpireTime80);
+ }
+
+ @Test
+ public void getTGT_returnsNullWhenNoTgt() {
+ Subject subject = new Subject();
+ KerberosPrincipal client = new KerberosPrincipal("[email protected]");
+ KerberosPrincipal server = new
KerberosPrincipal("HTTP/[email protected]");
+ Date now = new Date();
+ Date end = new Date(System.currentTimeMillis() +
60_000);
+ Date renew = new Date(end.getTime() + 60_000);
+ KerberosTicket notTgt = new KerberosTicket(new byte[] {1}, client,
server, new byte[] {1}, 1, null, now, now, end, renew, null);
+ subject.getPrivateCredentials().add(notTgt);
+
+ assertNull(CredentialsProviderUtil.getTGT(subject));
+ }
+
+ @Test
+ public void login_success_returnsSubjectFromLoginContext() throws
Exception {
+ Subject subject = new Subject();
+ try (MockedConstruction<LoginContext> mocked =
mockConstruction(LoginContext.class, (mock, context) -> {
+ when(mock.getSubject()).thenReturn(subject);
+ })) {
+ Subject out = CredentialsProviderUtil.login("[email protected]",
"/tmp/user.keytab");
+ assertSame(subject, out);
+ verify(mocked.constructed().get(0), times(1)).login();
+ }
+ }
+
+ @Test
+ public void login_throwsPrivilegedActionException_whenLoginContextFails()
throws Exception {
+ try (MockedConstruction<LoginContext> mocked =
mockConstruction(LoginContext.class, (mock, context) -> {
+ doThrow(new LoginException("boom")).when(mock).login();
+ })) {
+ PrivilegedActionException pae =
assertThrows(PrivilegedActionException.class, () ->
CredentialsProviderUtil.login("[email protected]", "/tmp/user.keytab"));
+ assertTrue(pae.getException() instanceof LoginException);
+ assertEquals("boom", pae.getException().getMessage());
+ }
+ }
+}
diff --git
a/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KerberosCredentialsProviderTest.java
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KerberosCredentialsProviderTest.java
new file mode 100644
index 000000000..eb9ad60b9
--- /dev/null
+++
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KerberosCredentialsProviderTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.credutils.kerberos;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.client.config.AuthSchemes;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for KerberosCredentialsProvider
+ */
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class KerberosCredentialsProviderTest {
+ @Test
+ public void setCredentials_acceptsOnlySpnego() {
+ KerberosCredentialsProvider provider = new
KerberosCredentialsProvider();
+ Credentials creds = mock(Credentials.class);
+
+ AuthScope spnego = new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO);
+ assertDoesNotThrow(() -> provider.setCredentials(spnego, creds));
+
+ AuthScope basic = new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.BASIC);
+ IllegalArgumentException ex =
assertThrows(IllegalArgumentException.class, () ->
provider.setCredentials(basic, creds));
+ assertTrue(ex.getMessage().contains(AuthSchemes.SPNEGO));
+ }
+
+ @Test
+ public void getCredentials_matchesOnScope_andReturnsNullWhenNoMatch() {
+ KerberosCredentialsProvider provider = new
KerberosCredentialsProvider();
+ Credentials creds = mock(Credentials.class);
+ AuthScope setScope = new AuthScope("host", 8080,
AuthScope.ANY_REALM, AuthSchemes.SPNEGO);
+ provider.setCredentials(setScope, creds);
+
+ // exact match
+ assertSame(creds, provider.getCredentials(new AuthScope("host", 8080,
AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
+ // partial match with ANY_HOST/ANY_PORT should still match
+ assertSame(creds, provider.getCredentials(new
AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM,
AuthSchemes.SPNEGO)));
+ // different scheme should not match
+ assertNull(provider.getCredentials(new AuthScope("host", 8080,
AuthScope.ANY_REALM, AuthSchemes.BASIC)));
+ // null arg returns null
+ assertNull(provider.getCredentials(null));
+ }
+
+ @Test
+ public void clear_resetsState() {
+ KerberosCredentialsProvider provider = new
KerberosCredentialsProvider();
+ Credentials creds = mock(Credentials.class);
+ provider.setCredentials(new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO), creds);
+
+ assertNotNull(provider.getCredentials(new
AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM,
AuthSchemes.SPNEGO)));
+ provider.clear();
+ assertNull(provider.getCredentials(new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
+ }
+}
diff --git
a/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KeytabJaasConfTest.java
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KeytabJaasConfTest.java
new file mode 100644
index 000000000..af061d539
--- /dev/null
+++
b/agents-cred/src/test/java/org/apache/ranger/authorization/credutils/kerberos/KeytabJaasConfTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.credutils.kerberos;
+
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.security.auth.login.AppConfigurationEntry;
+
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * @generated by Cursor
+ * @description : Unit Test cases for KeytabJaasConf
+ */
+
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
+public class KeytabJaasConfTest {
+ @Test
+ public void
getAppConfigurationEntry_includesExpectedOptions_andIsImmutable() {
+ KeytabJaasConf conf = new
KeytabJaasConf("[email protected]", "/tmp/user.keytab", true);
+ AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("any");
+ assertNotNull(entries);
+ assertEquals(1, entries.length);
+
+ AppConfigurationEntry entry = entries[0];
+ assertEquals("com.sun.security.auth.module.Krb5LoginModule",
entry.getLoginModuleName());
+ assertEquals(AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
entry.getControlFlag());
+
+ Map<String, ?> options = entry.getOptions();
+ assertEquals("[email protected]", options.get("principal"));
+ assertEquals(Boolean.TRUE.toString(), options.get("isInitiator"));
+ assertEquals(Boolean.TRUE.toString(), options.get("storeKey"));
+ assertEquals(Boolean.TRUE.toString(), options.get("debug"));
+ assertEquals(Boolean.TRUE.toString(), options.get("useKeyTab"));
+ assertEquals("/tmp/user.keytab", options.get("keyTab"));
+ assertEquals(Boolean.TRUE.toString(), options.get("doNotPrompt"));
+
+ assertThrows(UnsupportedOperationException.class, () -> ((Map)
options).put("x", "y"));
+ }
+
+ @Test
+ public void getAppConfigurationEntry_respectsDebugFlag() {
+ KeytabJaasConf conf = new
KeytabJaasConf("[email protected]", "/tmp/user.keytab", false);
+ AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("any");
+ Map<String, ?> options = entries[0].getOptions();
+ assertEquals(Boolean.FALSE.toString(), options.get("debug"));
+ }
+}
diff --git
a/agents-cred/src/test/java/org/apache/ranger/authorization/hadoop/utils/RangerCredentialProviderTest.java
b/agents-cred/src/test/java/org/apache/ranger/authorization/hadoop/utils/RangerCredentialProviderTest.java
index dcfe5e4da..97c2e85fc 100644
---
a/agents-cred/src/test/java/org/apache/ranger/authorization/hadoop/utils/RangerCredentialProviderTest.java
+++
b/agents-cred/src/test/java/org/apache/ranger/authorization/hadoop/utils/RangerCredentialProviderTest.java
@@ -23,14 +23,21 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+@ExtendWith(MockitoExtension.class)
+@TestMethodOrder(MethodOrderer.MethodName.class)
public class RangerCredentialProviderTest {
private final File ksFile;
private final String[] argsCreate;
@@ -128,6 +135,13 @@ public void testCredentialString() {
listThreads();
}
+ @Test
+ public void testGetInstanceSingleton() {
+ RangerCredentialProvider first =
RangerCredentialProvider.getInstance();
+ RangerCredentialProvider second =
RangerCredentialProvider.getInstance();
+ assertSame(first, second);
+ }
+
@After
public void teardown() throws Exception {
System.out.println("In teardown : Number of active Threads : " +
Thread.activeCount());