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