1895b87d2SChris Fraire /* 2895b87d2SChris Fraire * CDDL HEADER START 3895b87d2SChris Fraire * 4895b87d2SChris Fraire * The contents of this file are subject to the terms of the 5895b87d2SChris Fraire * Common Development and Distribution License (the "License"). 6895b87d2SChris Fraire * You may not use this file except in compliance with the License. 7895b87d2SChris Fraire * 8895b87d2SChris Fraire * See LICENSE.txt included in this distribution for the specific 9895b87d2SChris Fraire * language governing permissions and limitations under the License. 10895b87d2SChris Fraire * 11895b87d2SChris Fraire * When distributing Covered Code, include this CDDL HEADER in each 12895b87d2SChris Fraire * file and include the License file at LICENSE.txt. 13895b87d2SChris Fraire * If applicable, add the following below this CDDL HEADER, with the 14895b87d2SChris Fraire * fields enclosed by brackets "[]" replaced with your own identifying 15895b87d2SChris Fraire * information: Portions Copyright [yyyy] [name of copyright owner] 16895b87d2SChris Fraire * 17895b87d2SChris Fraire * CDDL HEADER END 18895b87d2SChris Fraire */ 19895b87d2SChris Fraire 20895b87d2SChris Fraire /* 21895b87d2SChris Fraire * Copyright (c) 2020, Chris Fraire <cfraire@me.com>. 222f7dccc7SAdam Hornacek * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. 23895b87d2SChris Fraire */ 24895b87d2SChris Fraire package opengrok.auth.plugin; 25895b87d2SChris Fraire 26895b87d2SChris Fraire import opengrok.auth.plugin.entity.User; 276c62ede9SAdam Hornacek import org.apache.commons.lang3.RandomStringUtils; 282f7dccc7SAdam Hornacek import org.junit.jupiter.api.AfterAll; 292f7dccc7SAdam Hornacek import org.junit.jupiter.api.BeforeAll; 302f7dccc7SAdam Hornacek import org.junit.jupiter.params.ParameterizedTest; 312f7dccc7SAdam Hornacek import org.junit.jupiter.params.provider.MethodSource; 32895b87d2SChris Fraire import org.opengrok.indexer.configuration.Group; 33895b87d2SChris Fraire import org.opengrok.indexer.configuration.Project; 34895b87d2SChris Fraire import org.opengrok.indexer.web.DummyHttpServletRequest; 35895b87d2SChris Fraire 36895b87d2SChris Fraire import java.io.BufferedWriter; 37895b87d2SChris Fraire import java.io.File; 38895b87d2SChris Fraire import java.io.FileOutputStream; 39ee1fba58SVladimir Kotal import java.io.IOException; 40895b87d2SChris Fraire import java.io.OutputStreamWriter; 41ee1fba58SVladimir Kotal import java.io.PrintWriter; 42895b87d2SChris Fraire import java.nio.charset.StandardCharsets; 43ee1fba58SVladimir Kotal import java.nio.file.Files; 441f3b8d68SVladimir Kotal import java.util.Arrays; 451f3b8d68SVladimir Kotal import java.util.Collection; 46895b87d2SChris Fraire import java.util.HashMap; 472f7dccc7SAdam Hornacek import java.util.Map; 48ee1fba58SVladimir Kotal import java.util.Set; 49ee1fba58SVladimir Kotal import java.util.stream.Collectors; 50ee1fba58SVladimir Kotal import java.util.stream.Stream; 51895b87d2SChris Fraire 52ee1fba58SVladimir Kotal import static org.junit.jupiter.api.Assertions.assertEquals; 532f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertFalse; 542f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull; 55895b87d2SChris Fraire import static org.junit.jupiter.api.Assertions.assertThrows; 562f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertTrue; 57895b87d2SChris Fraire 58895b87d2SChris Fraire /** 59895b87d2SChris Fraire * Represents a container for tests of {@link UserWhiteListPlugin}. 60895b87d2SChris Fraire */ 61895b87d2SChris Fraire public class UserWhiteListPluginTest { 62895b87d2SChris Fraire 63895b87d2SChris Fraire private static final String OK_USER = "user1321"; 641f3b8d68SVladimir Kotal private static final String OK_ID = "id2178"; 651f3b8d68SVladimir Kotal private static File tempWhitelistUser; 661f3b8d68SVladimir Kotal private static File tempWhitelistId; 67895b87d2SChris Fraire private static HashMap<String, Object> validPluginParameters; 68895b87d2SChris Fraire 69895b87d2SChris Fraire private UserWhiteListPlugin plugin; 701f3b8d68SVladimir Kotal parameters()711f3b8d68SVladimir Kotal public static Collection<String> parameters() { 721f3b8d68SVladimir Kotal return Arrays.asList(UserWhiteListPlugin.ID_FIELD, UserWhiteListPlugin.USERNAME_FIELD); 731f3b8d68SVladimir Kotal } 741f3b8d68SVladimir Kotal 752f7dccc7SAdam Hornacek @BeforeAll beforeClass()76895b87d2SChris Fraire public static void beforeClass() throws Exception { 771f3b8d68SVladimir Kotal tempWhitelistUser = File.createTempFile("UserWhiteListPluginTestUser", "txt"); 78895b87d2SChris Fraire try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( 791f3b8d68SVladimir Kotal new FileOutputStream(tempWhitelistUser), StandardCharsets.UTF_8))) { 80895b87d2SChris Fraire writer.write(OK_USER); 81895b87d2SChris Fraire // Don't bother with trailing LF. 82895b87d2SChris Fraire } 83895b87d2SChris Fraire 841f3b8d68SVladimir Kotal tempWhitelistId = File.createTempFile("UserWhiteListPluginTestId", "txt"); 851f3b8d68SVladimir Kotal try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( 861f3b8d68SVladimir Kotal new FileOutputStream(tempWhitelistId), StandardCharsets.UTF_8))) { 871f3b8d68SVladimir Kotal writer.write(OK_ID); 881f3b8d68SVladimir Kotal // Don't bother with trailing LF. 891f3b8d68SVladimir Kotal } 901f3b8d68SVladimir Kotal 91895b87d2SChris Fraire validPluginParameters = new HashMap<>(); 92895b87d2SChris Fraire } 93895b87d2SChris Fraire 942f7dccc7SAdam Hornacek @AfterAll afterClass()95895b87d2SChris Fraire public static void afterClass() { 961f3b8d68SVladimir Kotal if (tempWhitelistUser != null) { 97895b87d2SChris Fraire //noinspection ResultOfMethodCallIgnored 981f3b8d68SVladimir Kotal tempWhitelistUser.delete(); 991f3b8d68SVladimir Kotal } 1001f3b8d68SVladimir Kotal if (tempWhitelistId != null) { 1011f3b8d68SVladimir Kotal //noinspection ResultOfMethodCallIgnored 1021f3b8d68SVladimir Kotal tempWhitelistId.delete(); 103895b87d2SChris Fraire } 104895b87d2SChris Fraire } 105895b87d2SChris Fraire init(String param)1062f7dccc7SAdam Hornacek public void init(String param) { 107895b87d2SChris Fraire plugin = new UserWhiteListPlugin(); 1082f7dccc7SAdam Hornacek validPluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param); 1092f7dccc7SAdam Hornacek if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) { 1101f3b8d68SVladimir Kotal validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath()); 1111f3b8d68SVladimir Kotal } else { 1121f3b8d68SVladimir Kotal validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistId.getPath()); 1131f3b8d68SVladimir Kotal } 114895b87d2SChris Fraire } 115895b87d2SChris Fraire 1162f7dccc7SAdam Hornacek @ParameterizedTest 1172f7dccc7SAdam Hornacek @MethodSource("parameters") shouldThrowOnLoadIfNullArgument(String param)1182f7dccc7SAdam Hornacek public void shouldThrowOnLoadIfNullArgument(String param) { 1192f7dccc7SAdam Hornacek init(param); 120*4ceb1b98SVladimir Kotal assertThrows(IllegalArgumentException.class, () -> { 121895b87d2SChris Fraire //noinspection ConstantConditions 122895b87d2SChris Fraire plugin.load(null); 123895b87d2SChris Fraire }, "plugin.load(null)"); 124895b87d2SChris Fraire } 125895b87d2SChris Fraire 1262f7dccc7SAdam Hornacek @ParameterizedTest 1272f7dccc7SAdam Hornacek @MethodSource("parameters") shouldThrowOnLoadIfInvalidFieldName(String param)1282f7dccc7SAdam Hornacek public void shouldThrowOnLoadIfInvalidFieldName(String param) { 1292f7dccc7SAdam Hornacek init(param); 1301f3b8d68SVladimir Kotal assertThrows(IllegalArgumentException.class, () -> { 1312f7dccc7SAdam Hornacek Map<String, Object> map = new HashMap<>(); 1321f3b8d68SVladimir Kotal map.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath()); 1331f3b8d68SVladimir Kotal map.put(UserWhiteListPlugin.FIELD_PARAM, "huh"); 1341f3b8d68SVladimir Kotal plugin.load(map); 1351f3b8d68SVladimir Kotal }, "plugin.load(null)"); 1361f3b8d68SVladimir Kotal } 1371f3b8d68SVladimir Kotal 1382f7dccc7SAdam Hornacek @ParameterizedTest 1392f7dccc7SAdam Hornacek @MethodSource("parameters") shouldThrowOnLoadIfUnreadableFileSpecified(String param)1402f7dccc7SAdam Hornacek public void shouldThrowOnLoadIfUnreadableFileSpecified(String param) { 1412f7dccc7SAdam Hornacek init(param); 142895b87d2SChris Fraire HashMap<String, Object> unreadablePluginParameters = new HashMap<>(); 143895b87d2SChris Fraire unreadablePluginParameters.put(UserWhiteListPlugin.FILE_PARAM, 1446c62ede9SAdam Hornacek RandomStringUtils.randomAlphanumeric(24)); 145895b87d2SChris Fraire 146895b87d2SChris Fraire IllegalArgumentException caughtException = null; 147895b87d2SChris Fraire try { 148895b87d2SChris Fraire plugin.load(unreadablePluginParameters); 149895b87d2SChris Fraire } catch (IllegalArgumentException ex) { 150895b87d2SChris Fraire caughtException = ex; 151895b87d2SChris Fraire } 152895b87d2SChris Fraire 1532f7dccc7SAdam Hornacek assertNotNull(caughtException, "caught IllegalArgumentException"); 1542f7dccc7SAdam Hornacek assertTrue(caughtException.getMessage().contains("Unable to read the file"), 1552f7dccc7SAdam Hornacek "caughtException should mention 'Unable to read the file'"); 156895b87d2SChris Fraire } 157895b87d2SChris Fraire 1582f7dccc7SAdam Hornacek @ParameterizedTest 1592f7dccc7SAdam Hornacek @MethodSource("parameters") shouldThrowOnLoadIfNoFileSpecified(String param)1602f7dccc7SAdam Hornacek public void shouldThrowOnLoadIfNoFileSpecified(String param) { 1612f7dccc7SAdam Hornacek init(param); 162895b87d2SChris Fraire IllegalArgumentException caughtException = null; 163895b87d2SChris Fraire try { 164895b87d2SChris Fraire plugin.load(new HashMap<>()); 165895b87d2SChris Fraire } catch (IllegalArgumentException ex) { 166895b87d2SChris Fraire caughtException = ex; 167895b87d2SChris Fraire } 168895b87d2SChris Fraire 1692f7dccc7SAdam Hornacek assertNotNull(caughtException, "caught IllegalArgumentException"); 1702f7dccc7SAdam Hornacek assertTrue(caughtException.getMessage().contains("Missing parameter"), 1712f7dccc7SAdam Hornacek "caughtException should mention 'Missing parameter'"); 172895b87d2SChris Fraire } 173895b87d2SChris Fraire 1742f7dccc7SAdam Hornacek @ParameterizedTest 1752f7dccc7SAdam Hornacek @MethodSource("parameters") shouldStripWhitespaceFromWhitelists(String param)176ee1fba58SVladimir Kotal public void shouldStripWhitespaceFromWhitelists(String param) throws IOException { 177ee1fba58SVladimir Kotal plugin = new UserWhiteListPlugin(); 178ee1fba58SVladimir Kotal HashMap<String, Object> pluginParameters = new HashMap<>(); 179ee1fba58SVladimir Kotal pluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param); 180ee1fba58SVladimir Kotal Set<String> entries = Set.of("Moomin", " Fillyjonk", " Snuffkin", "Snork Maiden ", "Groke "); 181ee1fba58SVladimir Kotal 182ee1fba58SVladimir Kotal File tmpFile = File.createTempFile("UserWhiteListPluginTestId", "txt"); 183ee1fba58SVladimir Kotal try (PrintWriter writer = new PrintWriter(new OutputStreamWriter( 184ee1fba58SVladimir Kotal new FileOutputStream(tmpFile), StandardCharsets.UTF_8))) { 185ee1fba58SVladimir Kotal for (String entity : entries) { 186ee1fba58SVladimir Kotal writer.println(entity); 187ee1fba58SVladimir Kotal } 188ee1fba58SVladimir Kotal } 189ee1fba58SVladimir Kotal 190ee1fba58SVladimir Kotal // Make sure there as some entries with trailing spaces in the file. 191ee1fba58SVladimir Kotal Stream<String> stream = Files.lines(tmpFile.toPath()); 192ee1fba58SVladimir Kotal assertTrue(stream.filter(s -> s.startsWith(" ") || s.endsWith(" ")). 193ee1fba58SVladimir Kotal collect(Collectors.toSet()).size() > 0); 194ee1fba58SVladimir Kotal 195ee1fba58SVladimir Kotal pluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tmpFile.toString()); 196ee1fba58SVladimir Kotal plugin.load(pluginParameters); 197ee1fba58SVladimir Kotal tmpFile.delete(); 198ee1fba58SVladimir Kotal 199ee1fba58SVladimir Kotal Set<String> expected = entries.stream().map(String::trim).collect(Collectors.toSet()); 200ee1fba58SVladimir Kotal assertEquals(expected, plugin.getWhitelist()); 201ee1fba58SVladimir Kotal } 202ee1fba58SVladimir Kotal 203ee1fba58SVladimir Kotal @ParameterizedTest 204ee1fba58SVladimir Kotal @MethodSource("parameters") shouldUnload(String param)2052f7dccc7SAdam Hornacek public void shouldUnload(String param) { 2062f7dccc7SAdam Hornacek init(param); 207895b87d2SChris Fraire plugin.unload(); 208895b87d2SChris Fraire } 209895b87d2SChris Fraire 2102f7dccc7SAdam Hornacek @ParameterizedTest 2112f7dccc7SAdam Hornacek @MethodSource("parameters") shouldAllowWhitelistedUserForAnyProject(String param)2122f7dccc7SAdam Hornacek public void shouldAllowWhitelistedUserForAnyProject(String param) { 2132f7dccc7SAdam Hornacek init(param); 214895b87d2SChris Fraire plugin.load(validPluginParameters); 215895b87d2SChris Fraire 216895b87d2SChris Fraire DummyHttpServletRequest req = new DummyHttpServletRequest(); 2171f3b8d68SVladimir Kotal User user; 2182f7dccc7SAdam Hornacek if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) { 2191f3b8d68SVladimir Kotal user = new User(OK_USER); 2201f3b8d68SVladimir Kotal } else { 2211f3b8d68SVladimir Kotal user = new User("blurb", OK_ID); 2221f3b8d68SVladimir Kotal } 2231f3b8d68SVladimir Kotal req.setAttribute(UserPlugin.REQUEST_ATTR, user); 224895b87d2SChris Fraire 2256c62ede9SAdam Hornacek Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10)); 226895b87d2SChris Fraire boolean projectAllowed = plugin.isAllowed(req, randomProject); 2272f7dccc7SAdam Hornacek assertTrue(projectAllowed, "should allow OK entity for random project 1"); 228895b87d2SChris Fraire 2296c62ede9SAdam Hornacek randomProject = new Project(RandomStringUtils.randomAlphanumeric(10)); 230895b87d2SChris Fraire projectAllowed = plugin.isAllowed(req, randomProject); 2312f7dccc7SAdam Hornacek assertTrue(projectAllowed, "should allow OK entity for random project 2"); 232895b87d2SChris Fraire } 233895b87d2SChris Fraire 2342f7dccc7SAdam Hornacek @ParameterizedTest 2352f7dccc7SAdam Hornacek @MethodSource("parameters") shouldNotAllowRandomUserForAnyProject(String param)2362f7dccc7SAdam Hornacek public void shouldNotAllowRandomUserForAnyProject(String param) { 2372f7dccc7SAdam Hornacek init(param); 238895b87d2SChris Fraire plugin.load(validPluginParameters); 239895b87d2SChris Fraire 240895b87d2SChris Fraire DummyHttpServletRequest req = new DummyHttpServletRequest(); 2416c62ede9SAdam Hornacek req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8))); 242895b87d2SChris Fraire 2436c62ede9SAdam Hornacek Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10)); 244895b87d2SChris Fraire boolean projectAllowed = plugin.isAllowed(req, randomProject); 2452f7dccc7SAdam Hornacek assertFalse(projectAllowed, "should not allow random user for random project 1"); 246895b87d2SChris Fraire 2476c62ede9SAdam Hornacek randomProject = new Project(RandomStringUtils.randomAlphanumeric(10)); 248895b87d2SChris Fraire projectAllowed = plugin.isAllowed(req, randomProject); 2492f7dccc7SAdam Hornacek assertFalse(projectAllowed, "should not allow random user for random project 2"); 250895b87d2SChris Fraire } 251895b87d2SChris Fraire 2522f7dccc7SAdam Hornacek @ParameterizedTest 2532f7dccc7SAdam Hornacek @MethodSource("parameters") shouldAllowWhitelistedUserForAnyGroup(String param)2542f7dccc7SAdam Hornacek public void shouldAllowWhitelistedUserForAnyGroup(String param) { 2552f7dccc7SAdam Hornacek init(param); 256895b87d2SChris Fraire plugin.load(validPluginParameters); 257895b87d2SChris Fraire 258895b87d2SChris Fraire DummyHttpServletRequest req = new DummyHttpServletRequest(); 2591f3b8d68SVladimir Kotal User user; 2602f7dccc7SAdam Hornacek if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) { 2611f3b8d68SVladimir Kotal user = new User(OK_USER); 2621f3b8d68SVladimir Kotal } else { 2631f3b8d68SVladimir Kotal user = new User("blurb", OK_ID); 2641f3b8d68SVladimir Kotal } 2651f3b8d68SVladimir Kotal req.setAttribute(UserPlugin.REQUEST_ATTR, user); 266895b87d2SChris Fraire 2676c62ede9SAdam Hornacek Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10)); 268895b87d2SChris Fraire boolean groupAllowed = plugin.isAllowed(req, randomGroup); 2692f7dccc7SAdam Hornacek assertTrue(groupAllowed, "should allow OK entity for random group 1"); 270895b87d2SChris Fraire 2716c62ede9SAdam Hornacek randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10)); 272895b87d2SChris Fraire groupAllowed = plugin.isAllowed(req, randomGroup); 2732f7dccc7SAdam Hornacek assertTrue(groupAllowed, "should allow OK entity for random group 2"); 274895b87d2SChris Fraire } 275895b87d2SChris Fraire 2762f7dccc7SAdam Hornacek @ParameterizedTest 2772f7dccc7SAdam Hornacek @MethodSource("parameters") shouldNotAllowRandomUserForAnyGroup(String param)2782f7dccc7SAdam Hornacek public void shouldNotAllowRandomUserForAnyGroup(String param) { 2792f7dccc7SAdam Hornacek init(param); 280895b87d2SChris Fraire plugin.load(validPluginParameters); 281895b87d2SChris Fraire 282895b87d2SChris Fraire DummyHttpServletRequest req = new DummyHttpServletRequest(); 2836c62ede9SAdam Hornacek req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8))); 284895b87d2SChris Fraire 2856c62ede9SAdam Hornacek Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10)); 286895b87d2SChris Fraire boolean projectAllowed = plugin.isAllowed(req, randomGroup); 2872f7dccc7SAdam Hornacek assertFalse(projectAllowed, "should not allow random group 1"); 288895b87d2SChris Fraire 2896c62ede9SAdam Hornacek randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10)); 290895b87d2SChris Fraire projectAllowed = plugin.isAllowed(req, randomGroup); 2912f7dccc7SAdam Hornacek assertFalse(projectAllowed, "should not allow random group 2"); 292895b87d2SChris Fraire } 293895b87d2SChris Fraire } 294