Skip to content

Commit c1fe2be

Browse files
authored
RANGER-5351:Test Cases for agents-cred [ranger-plugins-cred] Module (#745)
1 parent 668b80b commit c1fe2be

5 files changed

Lines changed: 404 additions & 1 deletion

File tree

agents-cred/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@
118118
<version>${junit.jupiter.version}</version>
119119
<scope>test</scope>
120120
</dependency>
121+
<dependency>
122+
<groupId>org.mockito</groupId>
123+
<artifactId>mockito-inline</artifactId>
124+
<version>${mockito.version}</version>
125+
<scope>test</scope>
126+
</dependency>
127+
<dependency>
128+
<groupId>org.mockito</groupId>
129+
<artifactId>mockito-junit-jupiter</artifactId>
130+
<version>${mockito.version}</version>
131+
<scope>test</scope>
132+
</dependency>
121133
<dependency>
122134
<groupId>org.slf4j</groupId>
123135
<artifactId>log4j-over-slf4j</artifactId>
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
* <p>
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
* <p>
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.ranger.authorization.credutils;
19+
20+
import org.apache.http.auth.AuthScope;
21+
import org.apache.http.auth.Credentials;
22+
import org.apache.http.auth.UsernamePasswordCredentials;
23+
import org.apache.http.client.CredentialsProvider;
24+
import org.ietf.jgss.GSSCredential;
25+
import org.ietf.jgss.GSSException;
26+
import org.ietf.jgss.GSSManager;
27+
import org.ietf.jgss.GSSName;
28+
import org.ietf.jgss.Oid;
29+
import org.junit.jupiter.api.AfterEach;
30+
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.MethodOrderer;
32+
import org.junit.jupiter.api.Test;
33+
import org.junit.jupiter.api.TestMethodOrder;
34+
import org.junit.jupiter.api.extension.ExtendWith;
35+
import org.mockito.MockedConstruction;
36+
import org.mockito.MockedStatic;
37+
import org.mockito.junit.jupiter.MockitoExtension;
38+
39+
import javax.security.auth.Subject;
40+
import javax.security.auth.kerberos.KerberosPrincipal;
41+
import javax.security.auth.kerberos.KerberosTicket;
42+
import javax.security.auth.login.LoginContext;
43+
import javax.security.auth.login.LoginException;
44+
45+
import java.security.AccessControlContext;
46+
import java.security.AccessController;
47+
import java.security.PrivilegedActionException;
48+
import java.security.PrivilegedExceptionAction;
49+
import java.util.Date;
50+
51+
import static org.junit.jupiter.api.Assertions.assertEquals;
52+
import static org.junit.jupiter.api.Assertions.assertFalse;
53+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
54+
import static org.junit.jupiter.api.Assertions.assertNotNull;
55+
import static org.junit.jupiter.api.Assertions.assertNull;
56+
import static org.junit.jupiter.api.Assertions.assertSame;
57+
import static org.junit.jupiter.api.Assertions.assertThrows;
58+
import static org.junit.jupiter.api.Assertions.assertTrue;
59+
import static org.mockito.ArgumentMatchers.any;
60+
import static org.mockito.ArgumentMatchers.anyString;
61+
import static org.mockito.ArgumentMatchers.eq;
62+
import static org.mockito.Mockito.CALLS_REAL_METHODS;
63+
import static org.mockito.Mockito.doThrow;
64+
import static org.mockito.Mockito.mock;
65+
import static org.mockito.Mockito.mockConstruction;
66+
import static org.mockito.Mockito.mockStatic;
67+
import static org.mockito.Mockito.times;
68+
import static org.mockito.Mockito.verify;
69+
import static org.mockito.Mockito.when;
70+
71+
/**
72+
* @generated by Cursor
73+
* @description : Unit Test cases for CredentialsProviderUtil
74+
*/
75+
76+
@ExtendWith(MockitoExtension.class)
77+
@TestMethodOrder(MethodOrderer.MethodName.class)
78+
public class CredentialsProviderUtilTest {
79+
private MockedStatic<GSSManager> gssManagerStatic;
80+
private MockedStatic<AccessController> accessControllerStatic;
81+
82+
@BeforeEach
83+
public void setup() {
84+
CredentialsProviderUtil.ticketExpireTime80 = 0L;
85+
}
86+
87+
@AfterEach
88+
public void tearDown() {
89+
if (gssManagerStatic != null) {
90+
gssManagerStatic.close();
91+
}
92+
if (accessControllerStatic != null) {
93+
accessControllerStatic.close();
94+
}
95+
}
96+
97+
@Test
98+
public void getBasicCredentials_setsUsernamePasswordOnAnyScope() {
99+
CredentialsProvider provider = CredentialsProviderUtil.getBasicCredentials("user", "pass");
100+
Credentials creds = provider.getCredentials(AuthScope.ANY);
101+
assertNotNull(creds);
102+
assertInstanceOf(UsernamePasswordCredentials.class, creds);
103+
UsernamePasswordCredentials upc = (UsernamePasswordCredentials) creds;
104+
assertEquals("user", upc.getUserName());
105+
assertEquals("pass", upc.getPassword());
106+
}
107+
108+
@Test
109+
public void getKerberosCredentials_wrapsGssException() throws Exception {
110+
GSSManager mockManager = mock(GSSManager.class);
111+
gssManagerStatic = mockStatic(GSSManager.class);
112+
gssManagerStatic.when(GSSManager::getInstance).thenReturn(mockManager);
113+
when(mockManager.createName(anyString(), any())).thenThrow(new GSSException(GSSException.FAILURE));
114+
RuntimeException ex = assertThrows(RuntimeException.class, () -> CredentialsProviderUtil.getKerberosCredentials("user", "pw"));
115+
assertNotNull(ex.getCause());
116+
}
117+
118+
@Test
119+
public void getKerberosCredentials_wrapsPrivilegedActionException() throws Exception {
120+
GSSManager mockManager = mock(GSSManager.class);
121+
gssManagerStatic = mockStatic(GSSManager.class);
122+
gssManagerStatic.when(GSSManager::getInstance).thenReturn(mockManager);
123+
GSSName mockName = mock(GSSName.class);
124+
when(mockManager.createName(eq("user@EXAMPLE.COM"), eq(GSSName.NT_USER_NAME))).thenReturn(mockName);
125+
when(mockManager.createCredential(eq(mockName), eq(GSSCredential.DEFAULT_LIFETIME), any(Oid.class), eq(GSSCredential.INITIATE_ONLY))).thenThrow(new GSSException(GSSException.FAILURE));
126+
127+
try (MockedStatic<CredentialsProviderUtil> cpu = mockStatic(CredentialsProviderUtil.class, CALLS_REAL_METHODS)) {
128+
Subject subject = new Subject();
129+
cpu.when(() -> CredentialsProviderUtil.login(eq("user@EXAMPLE.COM"), eq("/tmp/keytab"))).thenReturn(subject);
130+
131+
RuntimeException ex = assertThrows(RuntimeException.class, () -> CredentialsProviderUtil.getKerberosCredentials("user@EXAMPLE.COM", "/tmp/keytab"));
132+
assertInstanceOf(PrivilegedActionException.class, ex.getCause());
133+
}
134+
}
135+
136+
@Test
137+
public void doAsPrivilegedWrapper_unwrapsNestedPrivilegedActionException() throws Exception {
138+
Subject subject = new Subject();
139+
PrivilegedActionException inner = new PrivilegedActionException(new Exception("root"));
140+
PrivilegedExceptionAction<Object> action = () -> {
141+
throw inner;
142+
};
143+
PrivilegedActionException thrown = assertThrows(PrivilegedActionException.class, () -> CredentialsProviderUtil.doAsPrivilegedWrapper(subject, action, mock(AccessControlContext.class)));
144+
assertInstanceOf(PrivilegedActionException.class, thrown.getCause());
145+
assertInstanceOf(Exception.class, thrown.getCause().getCause());
146+
assertEquals("root", thrown.getCause().getCause().getMessage());
147+
}
148+
149+
@Test
150+
public void getTGT_returnsTicketMatchingTgtPattern() {
151+
Subject subject = new Subject();
152+
KerberosPrincipal client = new KerberosPrincipal("user@EXAMPLE.COM");
153+
KerberosPrincipal server = new KerberosPrincipal("krbtgt/EXAMPLE.COM@EXAMPLE.COM");
154+
Date now = new Date();
155+
Date end = new Date(System.currentTimeMillis() + 60_000);
156+
Date renew = new Date(end.getTime() + 60_000);
157+
KerberosTicket tgt = new KerberosTicket(new byte[] {1}, client, server, new byte[] {1}, 1, null, now, now, end, renew, null);
158+
subject.getPrivateCredentials().add(tgt);
159+
160+
KerberosTicket found = CredentialsProviderUtil.getTGT(subject);
161+
assertNotNull(found);
162+
assertEquals(server, found.getServer());
163+
}
164+
165+
@Test
166+
public void ticketWillExpire_computes80PercentThresholdAndResets() {
167+
KerberosPrincipal client = new KerberosPrincipal("user@EXAMPLE.COM");
168+
KerberosPrincipal server = new KerberosPrincipal("krbtgt/EXAMPLE.COM@EXAMPLE.COM");
169+
Date start = new Date(System.currentTimeMillis() - 1000);
170+
Date end = new Date(System.currentTimeMillis() + 10_000);
171+
Date renew = new Date(end.getTime() + 10_000);
172+
KerberosTicket ticket = new KerberosTicket(new byte[] {1}, client, server, new byte[] {1}, 1, null, start, start, end, renew, null);
173+
174+
Boolean first = CredentialsProviderUtil.ticketWillExpire(ticket);
175+
assertFalse(first);
176+
CredentialsProviderUtil.ticketExpireTime80 = System.currentTimeMillis() - 1;
177+
Boolean second = CredentialsProviderUtil.ticketWillExpire(ticket);
178+
assertTrue(second);
179+
assertEquals(0L, CredentialsProviderUtil.ticketExpireTime80);
180+
}
181+
182+
@Test
183+
public void getTGT_returnsNullWhenNoTgt() {
184+
Subject subject = new Subject();
185+
KerberosPrincipal client = new KerberosPrincipal("user@EXAMPLE.COM");
186+
KerberosPrincipal server = new KerberosPrincipal("HTTP/host@EXAMPLE.COM");
187+
Date now = new Date();
188+
Date end = new Date(System.currentTimeMillis() + 60_000);
189+
Date renew = new Date(end.getTime() + 60_000);
190+
KerberosTicket notTgt = new KerberosTicket(new byte[] {1}, client, server, new byte[] {1}, 1, null, now, now, end, renew, null);
191+
subject.getPrivateCredentials().add(notTgt);
192+
193+
assertNull(CredentialsProviderUtil.getTGT(subject));
194+
}
195+
196+
@Test
197+
public void login_success_returnsSubjectFromLoginContext() throws Exception {
198+
Subject subject = new Subject();
199+
try (MockedConstruction<LoginContext> mocked = mockConstruction(LoginContext.class, (mock, context) -> {
200+
when(mock.getSubject()).thenReturn(subject);
201+
})) {
202+
Subject out = CredentialsProviderUtil.login("user@EXAMPLE.COM", "/tmp/user.keytab");
203+
assertSame(subject, out);
204+
verify(mocked.constructed().get(0), times(1)).login();
205+
}
206+
}
207+
208+
@Test
209+
public void login_throwsPrivilegedActionException_whenLoginContextFails() throws Exception {
210+
try (MockedConstruction<LoginContext> mocked = mockConstruction(LoginContext.class, (mock, context) -> {
211+
doThrow(new LoginException("boom")).when(mock).login();
212+
})) {
213+
PrivilegedActionException pae = assertThrows(PrivilegedActionException.class, () -> CredentialsProviderUtil.login("user@EXAMPLE.COM", "/tmp/user.keytab"));
214+
assertTrue(pae.getException() instanceof LoginException);
215+
assertEquals("boom", pae.getException().getMessage());
216+
}
217+
}
218+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.ranger.authorization.credutils.kerberos;
20+
21+
import org.apache.http.auth.AuthScope;
22+
import org.apache.http.auth.Credentials;
23+
import org.apache.http.client.config.AuthSchemes;
24+
import org.junit.jupiter.api.MethodOrderer;
25+
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.TestMethodOrder;
27+
import org.junit.jupiter.api.extension.ExtendWith;
28+
import org.mockito.junit.jupiter.MockitoExtension;
29+
30+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
31+
import static org.junit.jupiter.api.Assertions.assertNotNull;
32+
import static org.junit.jupiter.api.Assertions.assertNull;
33+
import static org.junit.jupiter.api.Assertions.assertSame;
34+
import static org.junit.jupiter.api.Assertions.assertThrows;
35+
import static org.junit.jupiter.api.Assertions.assertTrue;
36+
import static org.mockito.Mockito.mock;
37+
38+
/**
39+
* @generated by Cursor
40+
* @description : Unit Test cases for KerberosCredentialsProvider
41+
*/
42+
43+
@ExtendWith(MockitoExtension.class)
44+
@TestMethodOrder(MethodOrderer.MethodName.class)
45+
public class KerberosCredentialsProviderTest {
46+
@Test
47+
public void setCredentials_acceptsOnlySpnego() {
48+
KerberosCredentialsProvider provider = new KerberosCredentialsProvider();
49+
Credentials creds = mock(Credentials.class);
50+
51+
AuthScope spnego = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO);
52+
assertDoesNotThrow(() -> provider.setCredentials(spnego, creds));
53+
54+
AuthScope basic = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.BASIC);
55+
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> provider.setCredentials(basic, creds));
56+
assertTrue(ex.getMessage().contains(AuthSchemes.SPNEGO));
57+
}
58+
59+
@Test
60+
public void getCredentials_matchesOnScope_andReturnsNullWhenNoMatch() {
61+
KerberosCredentialsProvider provider = new KerberosCredentialsProvider();
62+
Credentials creds = mock(Credentials.class);
63+
AuthScope setScope = new AuthScope("host", 8080, AuthScope.ANY_REALM, AuthSchemes.SPNEGO);
64+
provider.setCredentials(setScope, creds);
65+
66+
// exact match
67+
assertSame(creds, provider.getCredentials(new AuthScope("host", 8080, AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
68+
// partial match with ANY_HOST/ANY_PORT should still match
69+
assertSame(creds, provider.getCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
70+
// different scheme should not match
71+
assertNull(provider.getCredentials(new AuthScope("host", 8080, AuthScope.ANY_REALM, AuthSchemes.BASIC)));
72+
// null arg returns null
73+
assertNull(provider.getCredentials(null));
74+
}
75+
76+
@Test
77+
public void clear_resetsState() {
78+
KerberosCredentialsProvider provider = new KerberosCredentialsProvider();
79+
Credentials creds = mock(Credentials.class);
80+
provider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO), creds);
81+
82+
assertNotNull(provider.getCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
83+
provider.clear();
84+
assertNull(provider.getCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.SPNEGO)));
85+
}
86+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.ranger.authorization.credutils.kerberos;
20+
21+
import org.junit.jupiter.api.MethodOrderer;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.TestMethodOrder;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
import org.mockito.junit.jupiter.MockitoExtension;
26+
27+
import javax.security.auth.login.AppConfigurationEntry;
28+
29+
import java.util.Map;
30+
31+
import static org.junit.jupiter.api.Assertions.assertEquals;
32+
import static org.junit.jupiter.api.Assertions.assertNotNull;
33+
import static org.junit.jupiter.api.Assertions.assertThrows;
34+
35+
/**
36+
* @generated by Cursor
37+
* @description : Unit Test cases for KeytabJaasConf
38+
*/
39+
40+
@ExtendWith(MockitoExtension.class)
41+
@TestMethodOrder(MethodOrderer.MethodName.class)
42+
public class KeytabJaasConfTest {
43+
@Test
44+
public void getAppConfigurationEntry_includesExpectedOptions_andIsImmutable() {
45+
KeytabJaasConf conf = new KeytabJaasConf("user@EXAMPLE.COM", "/tmp/user.keytab", true);
46+
AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("any");
47+
assertNotNull(entries);
48+
assertEquals(1, entries.length);
49+
50+
AppConfigurationEntry entry = entries[0];
51+
assertEquals("com.sun.security.auth.module.Krb5LoginModule", entry.getLoginModuleName());
52+
assertEquals(AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, entry.getControlFlag());
53+
54+
Map<String, ?> options = entry.getOptions();
55+
assertEquals("user@EXAMPLE.COM", options.get("principal"));
56+
assertEquals(Boolean.TRUE.toString(), options.get("isInitiator"));
57+
assertEquals(Boolean.TRUE.toString(), options.get("storeKey"));
58+
assertEquals(Boolean.TRUE.toString(), options.get("debug"));
59+
assertEquals(Boolean.TRUE.toString(), options.get("useKeyTab"));
60+
assertEquals("/tmp/user.keytab", options.get("keyTab"));
61+
assertEquals(Boolean.TRUE.toString(), options.get("doNotPrompt"));
62+
63+
assertThrows(UnsupportedOperationException.class, () -> ((Map) options).put("x", "y"));
64+
}
65+
66+
@Test
67+
public void getAppConfigurationEntry_respectsDebugFlag() {
68+
KeytabJaasConf conf = new KeytabJaasConf("user@EXAMPLE.COM", "/tmp/user.keytab", false);
69+
AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("any");
70+
Map<String, ?> options = entries[0].getOptions();
71+
assertEquals(Boolean.FALSE.toString(), options.get("debug"));
72+
}
73+
}

0 commit comments

Comments
 (0)