xref: /OpenGrok/plugins/src/test/java/opengrok/auth/plugin/LdapAttrPluginTest.java (revision b6621aef2373955443fcc262f30e58653b286ce3)
1b28a5538SAdam Hornacek /*
2b28a5538SAdam Hornacek  * CDDL HEADER START
3b28a5538SAdam Hornacek  *
4b28a5538SAdam Hornacek  * The contents of this file are subject to the terms of the
5b28a5538SAdam Hornacek  * Common Development and Distribution License (the "License").
6b28a5538SAdam Hornacek  * You may not use this file except in compliance with the License.
7b28a5538SAdam Hornacek  *
8b28a5538SAdam Hornacek  * See LICENSE.txt included in this distribution for the specific
9b28a5538SAdam Hornacek  * language governing permissions and limitations under the License.
10b28a5538SAdam Hornacek  *
11b28a5538SAdam Hornacek  * When distributing Covered Code, include this CDDL HEADER in each
12b28a5538SAdam Hornacek  * file and include the License file at LICENSE.txt.
13b28a5538SAdam Hornacek  * If applicable, add the following below this CDDL HEADER, with the
14b28a5538SAdam Hornacek  * fields enclosed by brackets "[]" replaced with your own identifying
15b28a5538SAdam Hornacek  * information: Portions Copyright [yyyy] [name of copyright owner]
16b28a5538SAdam Hornacek  *
17b28a5538SAdam Hornacek  * CDDL HEADER END
18b28a5538SAdam Hornacek  */
19b28a5538SAdam Hornacek 
20b28a5538SAdam Hornacek /*
210c92d7d9SVladimir Kotal  * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
22b28a5538SAdam Hornacek  */
23b28a5538SAdam Hornacek package opengrok.auth.plugin;
24b28a5538SAdam Hornacek 
25b28a5538SAdam Hornacek import java.io.File;
26b28a5538SAdam Hornacek import java.io.FileOutputStream;
27b28a5538SAdam Hornacek import java.io.IOException;
28b28a5538SAdam Hornacek import java.io.OutputStreamWriter;
29b28a5538SAdam Hornacek import java.io.Writer;
30b28a5538SAdam Hornacek import java.nio.file.Files;
31b28a5538SAdam Hornacek import java.util.Arrays;
32b28a5538SAdam Hornacek import java.util.Collections;
33f7f40d76SVladimir Kotal import java.util.HashMap;
34b28a5538SAdam Hornacek import java.util.Map;
35f7f40d76SVladimir Kotal import java.util.Set;
36b28a5538SAdam Hornacek import java.util.TreeMap;
37b28a5538SAdam Hornacek import java.util.TreeSet;
381161d3e8SAdam Hornacek 
39aa6abf42SAdam Hornacek import jakarta.servlet.http.HttpServletRequest;
40b28a5538SAdam Hornacek import opengrok.auth.entity.LdapUser;
41b28a5538SAdam Hornacek import opengrok.auth.plugin.entity.User;
42f7f40d76SVladimir Kotal import opengrok.auth.plugin.ldap.AbstractLdapProvider;
4341d15cd7SVladimir Kotal import opengrok.auth.plugin.ldap.FakeLdapFacade;
44f7f40d76SVladimir Kotal import opengrok.auth.plugin.ldap.LdapException;
45f7f40d76SVladimir Kotal import opengrok.auth.plugin.ldap.LdapFacade;
46b28a5538SAdam Hornacek import opengrok.auth.plugin.util.DummyHttpServletRequestLdap;
472f7dccc7SAdam Hornacek import org.junit.jupiter.api.AfterAll;
482f7dccc7SAdam Hornacek import org.junit.jupiter.api.BeforeAll;
492f7dccc7SAdam Hornacek import org.junit.jupiter.api.BeforeEach;
502f7dccc7SAdam Hornacek import org.junit.jupiter.api.Test;
51b28a5538SAdam Hornacek import org.opengrok.indexer.configuration.Group;
52b28a5538SAdam Hornacek import org.opengrok.indexer.configuration.Project;
53b28a5538SAdam Hornacek 
542f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertFalse;
552f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull;
562f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertTrue;
571161d3e8SAdam Hornacek import static org.mockito.ArgumentMatchers.any;
581161d3e8SAdam Hornacek import static org.mockito.ArgumentMatchers.anyString;
59f7f40d76SVladimir Kotal import static org.mockito.Mockito.mock;
60f7f40d76SVladimir Kotal import static org.mockito.Mockito.when;
61f7f40d76SVladimir Kotal 
62b28a5538SAdam Hornacek public class LdapAttrPluginTest {
63b28a5538SAdam Hornacek 
64b28a5538SAdam Hornacek     private HttpServletRequest dummyRequest;
65b28a5538SAdam Hornacek     private LdapAttrPlugin plugin;
66b28a5538SAdam Hornacek 
67b28a5538SAdam Hornacek     private static File whitelistFile;
68b28a5538SAdam Hornacek 
692f7dccc7SAdam Hornacek     @BeforeAll
beforeClass()70b28a5538SAdam Hornacek     public static void beforeClass() throws IOException {
71b28a5538SAdam Hornacek         whitelistFile = Files.createTempFile("opengrok-auth-", "-check.tmp").toFile();
72b28a5538SAdam Hornacek         try (Writer w = new OutputStreamWriter(new FileOutputStream(whitelistFile))) {
73b28a5538SAdam Hornacek             w.append("james@bond.com\n");
74b28a5538SAdam Hornacek             w.append("random@email.com\n");
75b28a5538SAdam Hornacek             w.append("just_a_text\n");
76b28a5538SAdam Hornacek         }
77b28a5538SAdam Hornacek     }
78b28a5538SAdam Hornacek 
792f7dccc7SAdam Hornacek     @AfterAll
afterClass()80b28a5538SAdam Hornacek     public static void afterClass() {
81*b6621aefSVladimir Kotal         whitelistFile.deleteOnExit();
82b28a5538SAdam Hornacek     }
83b28a5538SAdam Hornacek 
842f7dccc7SAdam Hornacek     @BeforeEach
setUp()85b28a5538SAdam Hornacek     public void setUp() {
86b28a5538SAdam Hornacek         plugin = new LdapAttrPlugin();
87b28a5538SAdam Hornacek         Map<String, Object> parameters = new TreeMap<>();
88b28a5538SAdam Hornacek 
89b28a5538SAdam Hornacek         parameters.put(LdapAttrPlugin.FILE_PARAM, whitelistFile.getAbsolutePath());
90b28a5538SAdam Hornacek         parameters.put(LdapAttrPlugin.ATTR_PARAM, "mail");
91b28a5538SAdam Hornacek 
9241d15cd7SVladimir Kotal         plugin.load(parameters, new FakeLdapFacade());
93b28a5538SAdam Hornacek     }
94b28a5538SAdam Hornacek 
prepareRequest(String username, String mail, String... ous)95b28a5538SAdam Hornacek     private void prepareRequest(String username, String mail, String... ous) {
96b28a5538SAdam Hornacek         dummyRequest = new DummyHttpServletRequestLdap();
97b28a5538SAdam Hornacek         dummyRequest.setAttribute(UserPlugin.REQUEST_ATTR,
98ef89dd12SVladimir Kotal                 new User(username, "123"));
99ef89dd12SVladimir Kotal 
100b28a5538SAdam Hornacek         LdapUser ldapUser = new LdapUser();
101b28a5538SAdam Hornacek         ldapUser.setAttribute("mail", new TreeSet<>(Collections.singletonList(mail)));
102b28a5538SAdam Hornacek         ldapUser.setAttribute("uid", new TreeSet<>(Collections.singletonList("123")));
103b28a5538SAdam Hornacek         ldapUser.setAttribute("ou", new TreeSet<>(Arrays.asList(ous)));
104ef89dd12SVladimir Kotal 
105b28a5538SAdam Hornacek         dummyRequest.getSession().setAttribute(LdapUserPlugin.SESSION_ATTR, ldapUser);
106b28a5538SAdam Hornacek         plugin.setSessionEstablished(dummyRequest, true);
107b28a5538SAdam Hornacek         plugin.setSessionUsername(dummyRequest, username);
108b28a5538SAdam Hornacek     }
109b28a5538SAdam Hornacek 
makeProject(String name)110b28a5538SAdam Hornacek     private Project makeProject(String name) {
111b28a5538SAdam Hornacek         Project p = new Project();
112b28a5538SAdam Hornacek         p.setName(name);
113b28a5538SAdam Hornacek         return p;
114b28a5538SAdam Hornacek     }
115b28a5538SAdam Hornacek 
makeGroup(String name)116b28a5538SAdam Hornacek     private Group makeGroup(String name) {
117b28a5538SAdam Hornacek         Group p = new Group();
118b28a5538SAdam Hornacek         p.setName(name);
119b28a5538SAdam Hornacek         return p;
120b28a5538SAdam Hornacek     }
121b28a5538SAdam Hornacek 
122b28a5538SAdam Hornacek     /**
123464d259bSVladimir Kotal      * Test of {@code isAllowed} method.
124b28a5538SAdam Hornacek      */
125b28a5538SAdam Hornacek     @Test
testIsAllowed()1260c92d7d9SVladimir Kotal     void testIsAllowed() {
127b28a5538SAdam Hornacek         /*
128b28a5538SAdam Hornacek          * whitelist[mail] => [james@bond.com, random@email.com, just_a_text]
129b28a5538SAdam Hornacek          */
130b28a5538SAdam Hornacek         prepareRequest("007", "james@bond.com", "MI6", "MI7");
131b28a5538SAdam Hornacek 
1321161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Random Project")));
1331161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Project 1")));
1341161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 1")));
1351161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 2")));
136b28a5538SAdam Hornacek 
137b28a5538SAdam Hornacek         prepareRequest("008", "james@bond.com", "MI6", "MI7");
138b28a5538SAdam Hornacek 
1391161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Random Project")));
1401161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Project 1")));
1411161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 1")));
1421161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 2")));
143b28a5538SAdam Hornacek 
144b28a5538SAdam Hornacek         prepareRequest("009", "other@email.com", "MI6");
145b28a5538SAdam Hornacek 
1462f7dccc7SAdam Hornacek         assertFalse(plugin.isAllowed(dummyRequest, makeProject("Random Project")));
1472f7dccc7SAdam Hornacek         assertFalse(plugin.isAllowed(dummyRequest, makeProject("Project 1")));
1482f7dccc7SAdam Hornacek         assertFalse(plugin.isAllowed(dummyRequest, makeGroup("Group 1")));
1492f7dccc7SAdam Hornacek         assertFalse(plugin.isAllowed(dummyRequest, makeGroup("Group 2")));
150b28a5538SAdam Hornacek 
151b28a5538SAdam Hornacek         prepareRequest("00A", "random@email.com", "MI6", "MI7");
152b28a5538SAdam Hornacek 
1531161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Random Project")));
1541161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeProject("Project 1")));
1551161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 1")));
1561161d3e8SAdam Hornacek         assertTrue(plugin.isAllowed(dummyRequest, makeGroup("Group 2")));
157b28a5538SAdam Hornacek     }
158f7f40d76SVladimir Kotal 
159f7f40d76SVladimir Kotal     /**
1601161d3e8SAdam Hornacek      * Test the interaction between {@code LdapUserPlugin} and {@code LdapAttrPlugin}. Namely:
161f7f40d76SVladimir Kotal      * <ul>
162f7f40d76SVladimir Kotal      *     <li>use of DN from the <code>LdapUser</code> object cached in the session by <code>LdapUserPlugin</code></li>
163f7f40d76SVladimir Kotal      *     <li>configuration of the cached session attribute name</li>
164f7f40d76SVladimir Kotal      * </ul>
165f7f40d76SVladimir Kotal      */
166f7f40d76SVladimir Kotal     @Test
testAttrLookup()1670c92d7d9SVladimir Kotal     void testAttrLookup() throws LdapException {
168f7f40d76SVladimir Kotal         String attr_to_get = "mail";
169f7f40d76SVladimir Kotal         String instance_num = "42";
170f7f40d76SVladimir Kotal         String mail_attr_value = "james@bond.com";
171f7f40d76SVladimir Kotal 
172df6e69cdSVladimir Kotal         // Create mock LDAP provider, simulating the work of LDAP server for LdapAttrPlugin#fillSession().
1738ce243f2SVladimir Kotal         AbstractLdapProvider mockProvider = mock(LdapFacade.class);
174f7f40d76SVladimir Kotal         Map<String, Set<String>> attrs = new HashMap<>();
175f7f40d76SVladimir Kotal         attrs.put(attr_to_get, Collections.singleton(mail_attr_value));
176f7f40d76SVladimir Kotal         final String dn = "cn=FOO_BAR,L=EMEA,DC=FOO,DC=COM";
177f7f40d76SVladimir Kotal         AbstractLdapProvider.LdapSearchResult<Map<String, Set<String>>> result =
178f7f40d76SVladimir Kotal                 new AbstractLdapProvider.LdapSearchResult<>(dn, attrs);
179f7f40d76SVladimir Kotal         assertNotNull(result);
18032c660d8SVladimir Kotal         when(mockProvider.lookupLdapContent(anyString(), any(String[].class))).thenReturn(result);
181f7f40d76SVladimir Kotal 
182f7f40d76SVladimir Kotal         // Load the LdapAttrPlugin using the mock LDAP provider.
183f7f40d76SVladimir Kotal         LdapAttrPlugin plugin = new LdapAttrPlugin();
184f7f40d76SVladimir Kotal         Map<String, Object> parameters = new TreeMap<>();
185f7f40d76SVladimir Kotal         parameters.put(LdapAttrPlugin.FILE_PARAM, whitelistFile.getAbsolutePath());
186f7f40d76SVladimir Kotal         parameters.put(LdapAttrPlugin.ATTR_PARAM, attr_to_get);
187f7f40d76SVladimir Kotal         parameters.put(LdapAttrPlugin.INSTANCE_PARAM, instance_num);
1888ce243f2SVladimir Kotal         plugin.load(parameters, mockProvider);
189f7f40d76SVladimir Kotal 
190f7f40d76SVladimir Kotal         LdapUser ldapUser = new LdapUser(dn, null);
191f7f40d76SVladimir Kotal         HttpServletRequest request = new DummyHttpServletRequestLdap();
192f7f40d76SVladimir Kotal         request.getSession().setAttribute(LdapUserPlugin.SESSION_ATTR + instance_num, ldapUser);
193f7f40d76SVladimir Kotal 
194f7f40d76SVladimir Kotal         // Here it comes all together.
1956e5f0873SVladimir Kotal         User user = new User("jbond", "007");
196f7f40d76SVladimir Kotal         plugin.fillSession(request, user);
197f7f40d76SVladimir Kotal 
198f7f40d76SVladimir Kotal         // See if LdapAttrPlugin set its own session attribute based on the mocked query.
199f7f40d76SVladimir Kotal         assertTrue((Boolean) request.getSession().getAttribute(plugin.getSessionAllowedAttrName()));
200f7f40d76SVladimir Kotal         assertTrue(ldapUser.getAttribute(attr_to_get).contains(mail_attr_value));
201f7f40d76SVladimir Kotal     }
202b28a5538SAdam Hornacek }
203