xref: /OpenGrok/plugins/src/test/java/opengrok/auth/plugin/UserWhiteListPluginTest.java (revision 4ceb1b98c17b7b580c0718bb27573b95081b34a5)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * See LICENSE.txt included in this distribution for the specific
9  * language governing permissions and limitations under the License.
10  *
11  * When distributing Covered Code, include this CDDL HEADER in each
12  * file and include the License file at LICENSE.txt.
13  * If applicable, add the following below this CDDL HEADER, with the
14  * fields enclosed by brackets "[]" replaced with your own identifying
15  * information: Portions Copyright [yyyy] [name of copyright owner]
16  *
17  * CDDL HEADER END
18  */
19 
20 /*
21  * Copyright (c) 2020, Chris Fraire <cfraire@me.com>.
22  * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
23  */
24 package opengrok.auth.plugin;
25 
26 import opengrok.auth.plugin.entity.User;
27 import org.apache.commons.lang3.RandomStringUtils;
28 import org.junit.jupiter.api.AfterAll;
29 import org.junit.jupiter.api.BeforeAll;
30 import org.junit.jupiter.params.ParameterizedTest;
31 import org.junit.jupiter.params.provider.MethodSource;
32 import org.opengrok.indexer.configuration.Group;
33 import org.opengrok.indexer.configuration.Project;
34 import org.opengrok.indexer.web.DummyHttpServletRequest;
35 
36 import java.io.BufferedWriter;
37 import java.io.File;
38 import java.io.FileOutputStream;
39 import java.io.IOException;
40 import java.io.OutputStreamWriter;
41 import java.io.PrintWriter;
42 import java.nio.charset.StandardCharsets;
43 import java.nio.file.Files;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.HashMap;
47 import java.util.Map;
48 import java.util.Set;
49 import java.util.stream.Collectors;
50 import java.util.stream.Stream;
51 
52 import static org.junit.jupiter.api.Assertions.assertEquals;
53 import static org.junit.jupiter.api.Assertions.assertFalse;
54 import static org.junit.jupiter.api.Assertions.assertNotNull;
55 import static org.junit.jupiter.api.Assertions.assertThrows;
56 import static org.junit.jupiter.api.Assertions.assertTrue;
57 
58 /**
59  * Represents a container for tests of {@link UserWhiteListPlugin}.
60  */
61 public class UserWhiteListPluginTest {
62 
63     private static final String OK_USER = "user1321";
64     private static final String OK_ID = "id2178";
65     private static File tempWhitelistUser;
66     private static File tempWhitelistId;
67     private static HashMap<String, Object> validPluginParameters;
68 
69     private UserWhiteListPlugin plugin;
70 
parameters()71     public static Collection<String> parameters() {
72         return Arrays.asList(UserWhiteListPlugin.ID_FIELD, UserWhiteListPlugin.USERNAME_FIELD);
73     }
74 
75     @BeforeAll
beforeClass()76     public static void beforeClass() throws Exception {
77         tempWhitelistUser = File.createTempFile("UserWhiteListPluginTestUser", "txt");
78         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
79                 new FileOutputStream(tempWhitelistUser), StandardCharsets.UTF_8))) {
80             writer.write(OK_USER);
81             // Don't bother with trailing LF.
82         }
83 
84         tempWhitelistId = File.createTempFile("UserWhiteListPluginTestId", "txt");
85         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
86                 new FileOutputStream(tempWhitelistId), StandardCharsets.UTF_8))) {
87             writer.write(OK_ID);
88             // Don't bother with trailing LF.
89         }
90 
91         validPluginParameters = new HashMap<>();
92     }
93 
94     @AfterAll
afterClass()95     public static void afterClass() {
96         if (tempWhitelistUser != null) {
97             //noinspection ResultOfMethodCallIgnored
98             tempWhitelistUser.delete();
99         }
100         if (tempWhitelistId != null) {
101             //noinspection ResultOfMethodCallIgnored
102             tempWhitelistId.delete();
103         }
104     }
105 
init(String param)106     public void init(String param) {
107         plugin = new UserWhiteListPlugin();
108         validPluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param);
109         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
110             validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath());
111         } else {
112             validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistId.getPath());
113         }
114     }
115 
116     @ParameterizedTest
117     @MethodSource("parameters")
shouldThrowOnLoadIfNullArgument(String param)118     public void shouldThrowOnLoadIfNullArgument(String param) {
119         init(param);
120         assertThrows(IllegalArgumentException.class, () -> {
121             //noinspection ConstantConditions
122             plugin.load(null);
123             }, "plugin.load(null)");
124     }
125 
126     @ParameterizedTest
127     @MethodSource("parameters")
shouldThrowOnLoadIfInvalidFieldName(String param)128     public void shouldThrowOnLoadIfInvalidFieldName(String param) {
129         init(param);
130         assertThrows(IllegalArgumentException.class, () -> {
131             Map<String, Object> map = new HashMap<>();
132             map.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath());
133             map.put(UserWhiteListPlugin.FIELD_PARAM, "huh");
134             plugin.load(map);
135         }, "plugin.load(null)");
136     }
137 
138     @ParameterizedTest
139     @MethodSource("parameters")
shouldThrowOnLoadIfUnreadableFileSpecified(String param)140     public void shouldThrowOnLoadIfUnreadableFileSpecified(String param) {
141         init(param);
142         HashMap<String, Object> unreadablePluginParameters = new HashMap<>();
143         unreadablePluginParameters.put(UserWhiteListPlugin.FILE_PARAM,
144                 RandomStringUtils.randomAlphanumeric(24));
145 
146         IllegalArgumentException caughtException = null;
147         try {
148             plugin.load(unreadablePluginParameters);
149         } catch (IllegalArgumentException ex) {
150             caughtException = ex;
151         }
152 
153         assertNotNull(caughtException, "caught IllegalArgumentException");
154         assertTrue(caughtException.getMessage().contains("Unable to read the file"),
155                 "caughtException should mention 'Unable to read the file'");
156     }
157 
158     @ParameterizedTest
159     @MethodSource("parameters")
shouldThrowOnLoadIfNoFileSpecified(String param)160     public void shouldThrowOnLoadIfNoFileSpecified(String param) {
161         init(param);
162         IllegalArgumentException caughtException = null;
163         try {
164             plugin.load(new HashMap<>());
165         } catch (IllegalArgumentException ex) {
166             caughtException = ex;
167         }
168 
169         assertNotNull(caughtException, "caught IllegalArgumentException");
170         assertTrue(caughtException.getMessage().contains("Missing parameter"),
171                 "caughtException should mention 'Missing parameter'");
172     }
173 
174     @ParameterizedTest
175     @MethodSource("parameters")
shouldStripWhitespaceFromWhitelists(String param)176     public void shouldStripWhitespaceFromWhitelists(String param) throws IOException {
177         plugin = new UserWhiteListPlugin();
178         HashMap<String, Object> pluginParameters = new HashMap<>();
179         pluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param);
180         Set<String> entries = Set.of("Moomin", " Fillyjonk", "  Snuffkin", "Snork Maiden  ", "Groke ");
181 
182         File tmpFile = File.createTempFile("UserWhiteListPluginTestId", "txt");
183         try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
184                 new FileOutputStream(tmpFile), StandardCharsets.UTF_8))) {
185             for (String entity : entries) {
186                 writer.println(entity);
187             }
188         }
189 
190         // Make sure there as some entries with trailing spaces in the file.
191         Stream<String> stream = Files.lines(tmpFile.toPath());
192         assertTrue(stream.filter(s -> s.startsWith(" ") || s.endsWith(" ")).
193                 collect(Collectors.toSet()).size() > 0);
194 
195         pluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tmpFile.toString());
196         plugin.load(pluginParameters);
197         tmpFile.delete();
198 
199         Set<String> expected = entries.stream().map(String::trim).collect(Collectors.toSet());
200         assertEquals(expected, plugin.getWhitelist());
201     }
202 
203     @ParameterizedTest
204     @MethodSource("parameters")
shouldUnload(String param)205     public void shouldUnload(String param) {
206         init(param);
207         plugin.unload();
208     }
209 
210     @ParameterizedTest
211     @MethodSource("parameters")
shouldAllowWhitelistedUserForAnyProject(String param)212     public void shouldAllowWhitelistedUserForAnyProject(String param) {
213         init(param);
214         plugin.load(validPluginParameters);
215 
216         DummyHttpServletRequest req = new DummyHttpServletRequest();
217         User user;
218         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
219             user = new User(OK_USER);
220         } else {
221             user = new User("blurb", OK_ID);
222         }
223         req.setAttribute(UserPlugin.REQUEST_ATTR, user);
224 
225         Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
226         boolean projectAllowed = plugin.isAllowed(req, randomProject);
227         assertTrue(projectAllowed, "should allow OK entity for random project 1");
228 
229         randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
230         projectAllowed = plugin.isAllowed(req, randomProject);
231         assertTrue(projectAllowed, "should allow OK entity for random project 2");
232     }
233 
234     @ParameterizedTest
235     @MethodSource("parameters")
shouldNotAllowRandomUserForAnyProject(String param)236     public void shouldNotAllowRandomUserForAnyProject(String param) {
237         init(param);
238         plugin.load(validPluginParameters);
239 
240         DummyHttpServletRequest req = new DummyHttpServletRequest();
241         req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8)));
242 
243         Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
244         boolean projectAllowed = plugin.isAllowed(req, randomProject);
245         assertFalse(projectAllowed, "should not allow random user for random project 1");
246 
247         randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
248         projectAllowed = plugin.isAllowed(req, randomProject);
249         assertFalse(projectAllowed, "should not allow random user for random project 2");
250     }
251 
252     @ParameterizedTest
253     @MethodSource("parameters")
shouldAllowWhitelistedUserForAnyGroup(String param)254     public void shouldAllowWhitelistedUserForAnyGroup(String param) {
255         init(param);
256         plugin.load(validPluginParameters);
257 
258         DummyHttpServletRequest req = new DummyHttpServletRequest();
259         User user;
260         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
261             user = new User(OK_USER);
262         } else {
263             user = new User("blurb", OK_ID);
264         }
265         req.setAttribute(UserPlugin.REQUEST_ATTR, user);
266 
267         Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
268         boolean groupAllowed = plugin.isAllowed(req, randomGroup);
269         assertTrue(groupAllowed, "should allow OK entity for random group 1");
270 
271         randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
272         groupAllowed = plugin.isAllowed(req, randomGroup);
273         assertTrue(groupAllowed, "should allow OK entity for random group 2");
274     }
275 
276     @ParameterizedTest
277     @MethodSource("parameters")
shouldNotAllowRandomUserForAnyGroup(String param)278     public void shouldNotAllowRandomUserForAnyGroup(String param) {
279         init(param);
280         plugin.load(validPluginParameters);
281 
282         DummyHttpServletRequest req = new DummyHttpServletRequest();
283         req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8)));
284 
285         Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
286         boolean projectAllowed = plugin.isAllowed(req, randomGroup);
287         assertFalse(projectAllowed, "should not allow random group 1");
288 
289         randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
290         projectAllowed = plugin.isAllowed(req, randomGroup);
291         assertFalse(projectAllowed, "should not allow random group 2");
292     }
293 }
294