Skip to content
Closed
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-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,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,74 @@
/*
* 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.hadoop.security;

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.Subject;
import javax.security.auth.callback.CallbackHandler;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @generated by Cursor
* @description <Unit Test for KrbPasswordSaverLoginModule class>
*/
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.MethodName.class)
public class TestKrbPasswordSaverLoginModule {
@Test
public void test01_initialize_storesCredentialsInSharedState() throws Exception {
KrbPasswordSaverLoginModule module = new KrbPasswordSaverLoginModule();
Map<String, Object> shared = new HashMap<>();
Map<String, Object> options = new HashMap<>();
options.put(KrbPasswordSaverLoginModule.USERNAME_PARAM, "user1");
options.put(KrbPasswordSaverLoginModule.PASSWORD_PARAM, "secret");

module.initialize(new Subject(), (CallbackHandler) null, shared, options);

assertEquals("user1", shared.get(KrbPasswordSaverLoginModule.USERNAME_PARAM));
assertArrayEquals("secret".toCharArray(), (char[]) shared.get(KrbPasswordSaverLoginModule.PASSWORD_PARAM));
}

@Test
public void test02_login_commit_abort_logout_returnTrue() throws Exception {
KrbPasswordSaverLoginModule module = new KrbPasswordSaverLoginModule();
assertTrue(module.login());
assertTrue(module.commit());
assertTrue(module.abort());
assertTrue(module.logout());
}

@Test
public void test03_initialize_withNullOptions_doesNotPopulateShared() {
KrbPasswordSaverLoginModule module = new KrbPasswordSaverLoginModule();
Map<String, Object> shared = new HashMap<>();
module.initialize(new Subject(), (CallbackHandler) null, shared, null);
assertTrue(shared.isEmpty());
}
}
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
*
* 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.hadoop.security;

import org.apache.hadoop.security.authentication.util.KerberosName;
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.Subject;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.security.Principal;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @generated by Cursor
* @description <Unit Test for SecureClientLogin class>
*/
@ExtendWith(MockitoExtension.class)
@TestMethodOrder(MethodOrderer.MethodName.class)
public class TestSecureClientLogin {
@Test
public void test01_isKerberosCredentialExists_nullKeytab_returnsFalse() {
boolean valid = SecureClientLogin.isKerberosCredentialExists("user@EXAMPLE.COM", null);
assertEquals(false, valid);
}

@Test
public void test02_isKerberosCredentialExists_missingFile_returnsFalse() {
File f = new File("/tmp/does-not-exist-" + System.nanoTime());
boolean valid = SecureClientLogin.isKerberosCredentialExists("user@EXAMPLE.COM", f.getAbsolutePath());
assertEquals(false, valid);
}

@Test
public void test03_isKerberosCredentialExists_existingFileAndPrincipal_returnsTrue() throws Exception {
File f = File.createTempFile("keytab", ".kt");
f.deleteOnExit();
try (FileWriter w = new FileWriter(f)) {
w.write("dummy");
}
boolean valid = SecureClientLogin.isKerberosCredentialExists("user@EXAMPLE.COM", f.getAbsolutePath());
assertEquals(true, valid);
}

@Test
public void test04_getPrincipal_noPattern_returnsSame() throws Exception {
String in = "user/host@EXAMPLE.COM";
String out = SecureClientLogin.getPrincipal(in, "host");
assertEquals(in, out);
}

@Test
public void test05_getPrincipal_withPatternAndHost_replacesWithLowercase() throws Exception {
String out = SecureClientLogin.getPrincipal("user/_HOST@EXAMPLE.COM", "FooBar.Example.COM");
assertEquals("user/foobar.example.com@EXAMPLE.COM", out);
}

@Test
public void test05b_getPrincipal_withPatternAndWildcardHost_usesLocalHost() throws Exception {
String out = SecureClientLogin.getPrincipal("user/_HOST@EXAMPLE.COM", "0.0.0.0");
assertTrue(out.startsWith("user/"));
assertTrue(out.endsWith("@EXAMPLE.COM"));
}

@Test
public void test06_getPrincipal_withNullHost_throwsIOException() {
assertThrows(IOException.class, () -> SecureClientLogin.getPrincipal("user/_HOST@EXAMPLE.COM", null));
}

@Test
public void test07_login_returnsSubjectWithPrincipal() throws Exception {
Subject s = SecureClientLogin.login("alice");
assertNotNull(s);
Set<Principal> principals = SecureClientLogin.getUserPrincipals(s);
assertNotNull(principals);
assertTrue(principals.stream().anyMatch(p -> "alice".equals(p.getName())));
}

@Test
public void test08_getUserPrincipals_nullSubject_returnsNull() {
assertNull(SecureClientLogin.getUserPrincipals(null));
}

@Test
public void test09_loginUserFromKeytab_invalid_throwsException() {
assertThrows(Exception.class,
() -> SecureClientLogin.loginUserFromKeytab("user@EXAMPLE.COM", "/path/not/found"));
}

@Test
public void test10_loginUserWithPassword_invalid_throwsException() {
assertThrows(Exception.class, () -> SecureClientLogin.loginUserWithPassword("user@EXAMPLE.COM", "badpass"));
}

@Test
public void test11_loginUserFromKeytab_withNameRules_invalid_throwsException() {
assertThrows(Exception.class,
() -> SecureClientLogin.loginUserFromKeytab("user@EXAMPLE.COM", "/path/not/found", "DEFAULT"));
}

@Test
public void test12_createUserPrincipal_returnsPrincipalWithName() {
Principal p = SecureClientLogin.createUserPrincipal("bob");
assertNotNull(p);
assertEquals("bob", p.getName());
}

@Test
public void test13_secureClientLoginConfiguration_withKeytab_returnsSingleKerberosEntry() {
SecureClientLogin.SecureClientLoginConfiguration conf = new SecureClientLogin.SecureClientLoginConfiguration(
true, "user@EXAMPLE.COM", "/tmp/fake.keytab");
AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("hadoop-keytab-kerberos");
assertNotNull(entries);
assertEquals(1, entries.length);
assertEquals(LoginModuleControlFlag.REQUIRED, entries[0].getControlFlag());
assertEquals("user@EXAMPLE.COM", entries[0].getOptions().get("principal"));
assertEquals("true", entries[0].getOptions().get("useKeyTab"));
assertEquals("/tmp/fake.keytab", entries[0].getOptions().get("keyTab"));
}

@Test
public void test14_secureClientLoginConfiguration_withPassword_returnsPwdSaverThenKerberos() {
SecureClientLogin.SecureClientLoginConfiguration conf = new SecureClientLogin.SecureClientLoginConfiguration(
false, "user@EXAMPLE.COM", "pwd");
AppConfigurationEntry[] entries = conf.getAppConfigurationEntry("hadoop-keytab-kerberos");
assertNotNull(entries);
assertEquals(2, entries.length);
assertEquals(KrbPasswordSaverLoginModule.class.getName(), entries[0].getLoginModuleName());
assertEquals("user@EXAMPLE.COM", entries[0].getOptions().get(KrbPasswordSaverLoginModule.USERNAME_PARAM));
assertEquals("pwd", entries[0].getOptions().get(KrbPasswordSaverLoginModule.PASSWORD_PARAM));
assertTrue(entries[1].getLoginModuleName().contains("Krb5LoginModule"));
}

@Test
public void test15_isKerberosCredentialExists_unreadableFile_returnsFalse() throws Exception {
File f = File.createTempFile("keytab", ".kt");
f.deleteOnExit();
try (FileWriter w = new FileWriter(f)) {
w.write("dummy");
}
// make unreadable if possible
boolean permChanged = f.setReadable(false, false);
// If permission cannot be changed in this environment, skip assert to avoid
// flakiness
if (permChanged) {
boolean valid = SecureClientLogin.isKerberosCredentialExists("user@EXAMPLE.COM", f.getAbsolutePath());
assertEquals(false, valid);
}
}

@Test
public void test16_isKerberosCredentialExists_emptyPrincipal_returnsFalse() throws Exception {
File f = File.createTempFile("keytab", ".kt");
f.deleteOnExit();
try (FileWriter w = new FileWriter(f)) {
w.write("dummy");
}
boolean valid = SecureClientLogin.isKerberosCredentialExists("", f.getAbsolutePath());
assertEquals(false, valid);
}

@Test
public void test17_loginUserFromKeytab_withInvalidNameRules_throwsIllegalArgumentException() {
assertThrows(IllegalArgumentException.class,
() -> SecureClientLogin.loginUserFromKeytab("user@EXAMPLE.COM", "/path/not/found", "INVALID_RULES_FORMAT"));
}

@Test
public void test18_loginUserFromKeytab_twoArg_catchesLoginException() {
String originalRules = "DEFAULT";
String allowExampleRule = "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\nDEFAULT";
try {
KerberosName.setRules(allowExampleRule);
assertThrows(IOException.class,
() -> SecureClientLogin.loginUserFromKeytab("user@EXAMPLE.COM", "/path/not/found"));
} finally {
KerberosName.setRules(originalRules);
}
}

@Test
public void test19_loginUserFromKeytab_threeArg_catchesLoginException() {
String originalRules = "DEFAULT";
String allowExampleRule = "RULE:[1:$1@$0](.*@EXAMPLE.COM)s/@.*//\nDEFAULT";
try {
assertThrows(IOException.class, () -> SecureClientLogin.loginUserFromKeytab("user@EXAMPLE.COM",
"/path/not/found", allowExampleRule));
} finally {
KerberosName.setRules(originalRules);
}
}
}
Loading
Loading