/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2010-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.web.springframework.security; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Collection; import java.util.Iterator; import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.opennms.core.test.MockLogAppender; import org.opennms.core.test.OpenNMSJUnit4ClassRunner; import org.opennms.core.utils.BeanUtils; import org.opennms.netmgt.config.GroupManager; import org.opennms.netmgt.config.UserManager; import org.opennms.netmgt.dao.db.JUnitConfigurationEnvironment; import org.opennms.netmgt.dao.db.JUnitTemporaryDatabase; import org.opennms.netmgt.model.OnmsUser; import org.opennms.test.FileAnticipator; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @RunWith(OpenNMSJUnit4ClassRunner.class) @ContextConfiguration(locations={ "classpath:/META-INF/opennms/applicationContext-dao.xml", "classpath*:/META-INF/opennms/component-dao.xml", "classpath:/META-INF/opennms/applicationContext-daemon.xml", "classpath:/META-INF/opennms/mockEventIpcManager.xml", "classpath:/META-INF/opennms/applicationContext-mock-usergroup.xml", "classpath:/META-INF/opennms/applicationContext-minimal-conf.xml", "classpath:/org/opennms/web/springframework/security/AuthenticationIntegrationTest-context.xml" }) @JUnitConfigurationEnvironment @JUnitTemporaryDatabase public class SpringSecurityUserDaoImplTest extends TestCase implements InitializingBean { private static final String MAGIC_USERS_FILE = "src/test/resources/org/opennms/web/springframework/security/magic-users.properties"; private static final String USERS_XML_FILE = "src/test/resources/org/opennms/web/springframework/security/users.xml"; @Autowired SpringSecurityUserDao m_springSecurityDao; @Autowired UserManager m_userManager; @Autowired GroupManager m_groupManager; @Override public void afterPropertiesSet() throws Exception { BeanUtils.assertAutowiring(this); } @Before public void setUp() { MockLogAppender.setupLogging(true, "DEBUG"); } @Test public void testGetByUsernameAdmin() { OnmsUser user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("admin"); assertNotNull("user object should not be null", user); assertEquals("OnmsUser name", "admin", user.getUsername()); assertEquals("Full name", "Administrator", user.getFullName()); assertEquals("Comments", null, user.getComments()); assertEquals("Password", "21232F297A57A5A743894A0E4A801FC3", user.getPassword()); Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); assertNotNull("authorities should not be null", authorities); assertEquals("authorities size", 2, authorities.size()); Iterator<? extends GrantedAuthority> itr = authorities.iterator(); assertEquals("authorities 0 name", Authentication.ROLE_USER, itr.next().getAuthority()); assertEquals("authorities 2 name", Authentication.ROLE_ADMIN, itr.next().getAuthority()); } @Test public void testGetByUsernameBogus() { assertNull("user object should be null", m_springSecurityDao.getByUsername("bogus")); } @Test public void testGetByUsernameRtc() { OnmsUser user = m_springSecurityDao.getByUsername("rtc"); assertNotNull("user object should not be null", user); assertEquals("OnmsUser name", "rtc", user.getUsername()); assertEquals("Full name", null, user.getFullName()); assertEquals("Comments", null, user.getComments()); assertTrue("Password", m_userManager.checkSaltedPassword("rtc", user.getPassword())); Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); assertNotNull("authorities should not be null", authorities); assertEquals("authorities size", 1, authorities.size()); assertEquals("authorities 0 name", Authentication.ROLE_RTC, authorities.iterator().next().getAuthority()); } @Test @DirtiesContext public void testGetByUsernameTempUser() throws Exception { final OnmsUser newUser = new OnmsUser("tempuser"); newUser.setPassword("18126E7BD3F84B3F3E4DF094DEF5B7DE"); m_userManager.save(newUser); final OnmsUser user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("tempuser"); assertNotNull("user object should not be null", user); assertEquals("OnmsUser name", "tempuser", user.getUsername()); assertEquals("Full name", null, user.getFullName()); assertEquals("Comments", null, user.getComments()); assertEquals("Password", "18126E7BD3F84B3F3E4DF094DEF5B7DE", user.getPassword()); Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); assertNotNull("authorities should not be null", authorities); assertEquals("authorities size", 1, authorities.size()); assertEquals("authorities 0 name", Authentication.ROLE_USER, authorities.iterator().next().getAuthority()); } @Test @DirtiesContext public void testGetByUsernameDashboard() throws Exception { final OnmsUser newUser = new OnmsUser("dashboard"); newUser.setPassword("DC7161BE3DBF2250C8954E560CC35060"); m_userManager.save(newUser); OnmsUser user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("dashboard"); assertNotNull("user object should not be null", user); assertEquals("OnmsUser name", "dashboard", user.getUsername()); assertEquals("Full name", null, user.getFullName()); assertEquals("Comments", null, user.getComments()); assertEquals("Password", "DC7161BE3DBF2250C8954E560CC35060", user.getPassword()); Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); assertNotNull("authorities should not be null", authorities); assertEquals("authorities size", 1, authorities.size()); assertEquals("authorities 0 name", Authentication.ROLE_DASHBOARD, authorities.iterator().next().getAuthority()); } @Test @DirtiesContext public void testMagicUsersReload() throws Exception { final OnmsUser newUser = new OnmsUser("dashboard"); newUser.setPassword("DC7161BE3DBF2250C8954E560CC35060"); m_userManager.save(newUser); /* * We're not going to use the anticipator functionality, but it's * handy for handling temporary directories. */ FileAnticipator fa = new FileAnticipator(); try { File users = fa.tempFile("users.xml"); File magicUsers = fa.tempFile("magic-users.properties"); writeTemporaryFile(users, getUsersXmlContents()); writeTemporaryFile(magicUsers, getMagicUsersContents()); ((SpringSecurityUserDaoImpl) m_springSecurityDao).setUsersConfigurationFile(users.getAbsolutePath()); ((SpringSecurityUserDaoImpl) m_springSecurityDao).setMagicUsersConfigurationFile(magicUsers.getAbsolutePath()); OnmsUser user; Collection<? extends GrantedAuthority> authorities; user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("dashboard"); assertNotNull("dashboard user should exist and the object should not be null", user); authorities = user.getAuthorities(); assertNotNull("user GrantedAuthorities[] object should not be null", authorities); assertEquals("user GrantedAuthorities[] object should have only one entry", 1, authorities.size()); assertEquals("user GrantedAuthorities[0]", Authentication.ROLE_DASHBOARD, authorities.iterator().next().getAuthority()); /* * On UNIX, the resolution of the last modified time is 1 second, * so we need to wait at least that long before rewriting the * file to ensure that we have crossed over into the next second. * At least we're not crossing over with John Edward. */ Thread.sleep(1100); writeTemporaryFile(magicUsers, getMagicUsersContents().replace("role.dashboard.users=dashboard", "role.dashboard.users=")); user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("dashboard"); assertNotNull("dashboard user should exist and the object should not be null", user); authorities = user.getAuthorities(); assertNotNull("user GrantedAuthorities[] object should not be null", authorities); assertEquals("user GrantedAuthorities[] object should have only one entry", 1, authorities.size()); assertEquals("user GrantedAuthorities[0]", Authentication.ROLE_USER, authorities.iterator().next().getAuthority()); } finally { fa.deleteExpected(); fa.tearDown(); } } /** * Test for bugzilla bug #1810. This is the case: * <ol> * <li>Both users and magic users files are loaded</li> * <li>Magic users file is changed</li> * <li>Magic users file is reloaded on the next call to getByUsername</li> * <li>Subsequent calls to getByUsername call caues a reload because the * last update time for the users file is stored when magic users is * reloaded</li> * </ol> * * @param file * @param content * @throws IOException */ @Test @DirtiesContext public void testMagicUsersReloadUpdateLastModified() throws Exception { final OnmsUser newUser = new OnmsUser("dashboard"); newUser.setPassword("DC7161BE3DBF2250C8954E560CC35060"); m_userManager.save(newUser); /* * We're not going to use the anticipator functionality, but it's * handy for handling temporary directories. */ FileAnticipator fa = new FileAnticipator(); try { File users = fa.tempFile("users.xml"); File magicUsers = fa.tempFile("magic-users.properties"); writeTemporaryFile(users, getUsersXmlContents()); writeTemporaryFile(magicUsers, getMagicUsersContents()); ((SpringSecurityUserDaoImpl) m_springSecurityDao).setUsersConfigurationFile(users.getAbsolutePath()); ((SpringSecurityUserDaoImpl) m_springSecurityDao).setMagicUsersConfigurationFile(magicUsers.getAbsolutePath()); OnmsUser user; Collection<? extends GrantedAuthority> authorities; user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("dashboard"); assertNotNull("dashboard user should exist and the object should not be null", user); authorities = user.getAuthorities(); assertNotNull("user GrantedAuthorities[] object should not be null", authorities); assertEquals("user GrantedAuthorities[] object should have only one entry", 1, authorities.size()); assertEquals("user GrantedAuthorities[0]", Authentication.ROLE_DASHBOARD, authorities.iterator().next().getAuthority()); /* * On UNIX, the resolution of the last modified time is 1 second, * so we need to wait at least that long before rewriting the * file to ensure that we have crossed over into the next second. * At least we're not crossing over with John Edward. */ Thread.sleep(1100); writeTemporaryFile(magicUsers, getMagicUsersContents().replace("role.dashboard.users=dashboard", "role.dashboard.users=")); user = ((SpringSecurityUserDao) m_springSecurityDao).getByUsername("dashboard"); assertNotNull("dashboard user should exist and the object should not be null", user); authorities = user.getAuthorities(); assertNotNull("user GrantedAuthorities[] object should not be null", authorities); assertEquals("user GrantedAuthorities[] object should have only one entry", 1, authorities.size()); assertEquals("user GrantedAuthorities[0]", Authentication.ROLE_USER, authorities.iterator().next().getAuthority()); long ourLastModifiedTime = magicUsers.lastModified(); long daoLastModifiedTime = ((SpringSecurityUserDaoImpl) m_springSecurityDao).getMagicUsersLastModified(); assertEquals("last modified time of magic users file does not match what the DAO stored after reloading the file", ourLastModifiedTime, daoLastModifiedTime); } finally { fa.deleteExpected(); fa.tearDown(); } } private void writeTemporaryFile(File file, String content) throws IOException { Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); writer.write(content); writer.close(); } private String getUsersXmlContents() throws IOException { return getFileContents(new File(USERS_XML_FILE)); } private String getMagicUsersContents() throws IOException { return getFileContents(new File(MAGIC_USERS_FILE)); } private String getFileContents(File file) throws FileNotFoundException, IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); StringBuffer contents = new StringBuffer(); String line; while ((line = reader.readLine()) != null) { contents.append(line); contents.append("\n"); } return contents.toString(); } }