Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions agents-cred/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/**
* 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
void setup() {
CredentialsProviderUtil.ticketExpireTime80 = 0L;
}

@AfterEach
void tearDown() {
if (gssManagerStatic != null) {
gssManagerStatic.close();
}
if (accessControllerStatic != null) {
accessControllerStatic.close();
}
}

@Test
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
void getKerberosCredentials_wrapsGssException() {
GSSManager mockManager = mock(GSSManager.class);
gssManagerStatic = mockStatic(GSSManager.class);
gssManagerStatic.when(GSSManager::getInstance).thenReturn(mockManager);
try {
when(mockManager.createName(anyString(), any())).thenThrow(new GSSException(GSSException.FAILURE));
} catch (GSSException e) {
// ignored
}
RuntimeException ex = assertThrows(RuntimeException.class, () -> CredentialsProviderUtil.getKerberosCredentials("user", "pw"));
assertNotNull(ex.getCause());
}

@Test
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
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
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
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
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
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
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());
}
}
}
Original file line number Diff line number Diff line change
@@ -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)));
}
}
Loading
Loading