package io.jenkins.plugins.audit.listeners; import com.gargoylesoftware.htmlunit.html.HtmlPage; import hudson.model.User; import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.pages.SignupPage; import jenkins.model.Jenkins; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.acegisecurity.Authentication; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.message.StructuredDataMessage; import org.apache.logging.log4j.test.appender.ListAppender; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.JenkinsRule.WebClient; import org.xml.sax.SAXException; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.List; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(JUnitParamsRunner.class) public class UserCreationListenerTest { private ListAppender app; private WebClient client; private final HashMap<String, String> USERS = new HashMap<String, String>(); private static void assertEventCount(final List<LogEvent> events, final int expected) { assertEquals("Incorrect number of events.", expected, events.size()); } private static WebClient logout(final WebClient wc) throws IOException, SAXException { wc.goTo("logout"); return wc; } @Rule public JenkinsRule j = new JenkinsRule(); @Before public void setup() throws Exception { // user ID conformance check Field field = HudsonPrivateSecurityRealm.class.getDeclaredField("ID_REGEX"); field.setAccessible(true); field.set(null, null); // credentials of four Jenkins accounts USERS.put("alice", "alicePassword"); USERS.put("bob", "bobPassword"); USERS.put("charlie", "charliePassword"); USERS.put("debbie", "debbiePassword"); client = j.createWebClient(); logout(client); app = ListAppender.getListAppender("AuditList").clear(); } @After public void teardown() { app.clear(); } @Issue("JENKINS-54088") @Test @Parameters({ "1, alice, alicePassword", "1, bob, bobPassword", "1, charlie, charliePassword", "1, debbie, debbiePassword" }) public void testUserCreationFromRealm(int expectedCount, String username, String password) throws Exception { assertEventCount(app.getEvents(), 0); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(realm); User user = realm.createAccount(username, password); user.save(); assertEventCount(app.getEvents(), expectedCount); } @Issue("JENKINS-54088") @Test public void testUserCreationFromSignUp() throws Exception { assertEventCount(app.getEvents(), 0); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(true, false, null); j.jenkins.setSecurityRealm(realm); SignupPage signup = new SignupPage(client.goTo("signup")); signup.enterUsername("debbie"); signup.enterPassword(USERS.get("debbie")); signup.enterFullName("Debbie User"); HtmlPage success = signup.submit(j); // user creation via a jenkins signup also automatically logs the user in assertEventCount(app.getEvents(), 2); // verify a login event occurred client.executeOnServer(() -> { Authentication a = Jenkins.getAuthentication(); assertEquals("debbie", a.getName()); return null; }); assertThat(success.getElementById("main-panel").getTextContent(), containsString("Success")); assertEquals("Debbie User", realm.getUser("debbie").getDisplayName()); } @Issue("JENKINS-54088") @Test public void testUserCreationAndLoginFromRealm() throws Exception { assertEventCount(app.getEvents(), 0); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(realm); User u1 = realm.createAccount("charlie", USERS.get("charlie")); u1.save(); client.login("charlie", USERS.get("charlie")); // verify the audit event log messages as user creation and user login events StructuredDataMessage logMessageOne = (StructuredDataMessage) app.getEvents().get(0).getMessage(); StructuredDataMessage logMessageTwo = (StructuredDataMessage) app.getEvents().get(1).getMessage(); assertTrue(logMessageOne.toString().contains("createUser")); assertTrue(logMessageTwo.toString().contains("login")); // verify a login event occurred client.executeOnServer(() -> { Authentication a = Jenkins.getAuthentication(); assertEquals("charlie", a.getName()); return null; }); assertEventCount(app.getEvents(), 2); } }