/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.xml; import static org.easymock.EasyMock.expect; import static org.easymock.classextension.EasyMock.createNiceMock; import static org.easymock.classextension.EasyMock.replay; import static org.geoserver.security.xml.XMLSecurityConfigException.CHECK_INTERVAL_INVALID; import static org.geoserver.security.xml.XMLSecurityConfigException.FILENAME_CHANGE_INVALID_$2; import static org.geoserver.security.xml.XMLSecurityConfigException.FILENAME_REQUIRED; import static org.geoserver.security.xml.XMLSecurityConfigException.FILE_CREATE_FAILED_$1; import static org.geoserver.security.xml.XMLSecurityConfigException.ROLE_SERVICE_NOT_EMPTY_$1; import static org.geoserver.security.xml.XMLSecurityConfigException.USERGROUP_SERVICE_NOT_EMPTY_$1; import static org.geoserver.security.xml.XMLSecurityConfigException.USERGROUP_SERVICE_REQUIRED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.TreeSet; import java.util.logging.Logger; import org.geoserver.platform.resource.Files; import org.geoserver.security.GeoServerRoleService; import org.geoserver.security.GeoServerSecurityManager; import org.geoserver.security.GeoServerUserGroupService; import org.geoserver.security.auth.UsernamePasswordAuthenticationProvider; import org.geoserver.security.config.SecurityAuthProviderConfig; import org.geoserver.security.config.SecurityRoleServiceConfig; import org.geoserver.security.config.SecurityUserGroupServiceConfig; import org.geoserver.security.impl.GeoServerUserGroup; import org.geoserver.security.password.PasswordValidator; import org.geoserver.security.validation.SecurityConfigException; import org.geoserver.security.validation.SecurityConfigValidatorTest; import org.geotools.util.logging.Logging; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class XMLSecurityConfigValidatorTest extends SecurityConfigValidatorTest { @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); static protected Logger LOGGER = Logging.getLogger("org.geoserver.security"); protected SecurityUserGroupServiceConfig createUGConfig(String name, Class<?> aClass, String encoder, String policyName, String fileName) { XMLUserGroupServiceConfig config = new XMLUserGroupServiceConfig(); config.setName(name); config.setClassName(aClass.getName()); config.setPasswordEncoderName(encoder); config.setPasswordPolicyName(policyName); config.setCheckInterval(0); config.setFileName(fileName); return config; } protected SecurityRoleServiceConfig createRoleConfig(String name, Class<?> aClass,String adminRole,String fileName) { XMLRoleServiceConfig config = new XMLRoleServiceConfig(); config.setName(name); config.setClassName(aClass.getName()); config.setAdminRoleName(adminRole); config.setCheckInterval(0); config.setFileName(fileName); return config; } @Test public void testRoleConfig() throws IOException{ super.testRoleConfig(); XMLRoleServiceConfig config = (XMLRoleServiceConfig )createRoleConfig(XMLRoleService.DEFAULT_NAME, XMLRoleService.class, XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE,XMLConstants.FILE_RR); XMLSecurityConfigValidator validator = new XMLSecurityConfigValidator(getSecurityManager()); try { config.setName("default2"); config.setCheckInterval(-1l); validator.validateAddRoleService(config); fail("invalid interval should fail"); //getSecurityManager().saveRoleService(config); } catch (SecurityConfigException ex) { assertEquals( CHECK_INTERVAL_INVALID,ex.getId()); assertEquals(0,ex.getArgs().length); } try { config.setCheckInterval(999l); validator.validateAddRoleService(config); fail("invalid interval should fail"); //getSecurityManager().saveRoleService(config); } catch (SecurityConfigException ex) { assertEquals( CHECK_INTERVAL_INVALID,ex.getId()); assertEquals(0,ex.getArgs().length); } config.setCheckInterval(0); XMLRoleServiceConfig xmlConfig = (XMLRoleServiceConfig) createRoleConfig("test1",XMLRoleService.class,XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE,"test1.xml"); try { validator.validateAddRoleService(xmlConfig); //getSecurityManager().saveRoleService(xmlConfig); } catch (SecurityConfigException ex) { fail("Should work but got: " + ex.getMessage()); } // run only if a temp dir is availbale if (new XMLSecurityConfigValidator(getSecurityManager()).getTempDir()!=null) { String invalidPath="abc"+File.separator+"def.xml"; XMLRoleServiceConfig xmlConfig4 = (XMLRoleServiceConfig) createRoleConfig("test4",XMLRoleService.class,XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE, invalidPath); try { validator.validateAddRoleService(xmlConfig4); fail("file creation failure should occur"); //getSecurityManager().saveRoleService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(FILE_CREATE_FAILED_$1, ex.getId()); assertEquals(invalidPath, ex.getArgs()[0]); } } GeoServerSecurityManager secMgr = createNiceMock(GeoServerSecurityManager.class); GeoServerRoleService roleService1 = createNiceMock(GeoServerRoleService.class); expect(roleService1.getRoleCount()).andReturn(0).anyTimes(); expect(secMgr.loadRoleService("test1")).andReturn(roleService1).anyTimes(); GeoServerRoleService roleService2 = createNiceMock(GeoServerRoleService.class); expect(roleService2.getRoleCount()).andReturn(1).anyTimes(); expect(secMgr.loadRoleService("test2")).andReturn(roleService2).anyTimes(); GeoServerRoleService roleService3 = createNiceMock(GeoServerRoleService.class); expect(roleService3.getRoleCount()).andReturn(1).anyTimes(); expect(secMgr.loadRoleService("test3")).andReturn(roleService3).anyTimes(); GeoServerRoleService roleService4 = createNiceMock(GeoServerRoleService.class); expect(roleService4.getRoleCount()).andReturn(1).anyTimes(); expect(secMgr.loadRoleService("test4")).andReturn(roleService4).anyTimes(); GeoServerRoleService activeRoleService = createNiceMock(GeoServerRoleService.class); expect(activeRoleService.getName()).andReturn("foo").anyTimes(); expect(secMgr.getActiveRoleService()).andReturn(activeRoleService).anyTimes(); expect(secMgr.role()).andReturn(Files.asResource(tempFolder.getRoot())).anyTimes(); expect(secMgr.listRoleServices()).andReturn(new TreeSet<String>( Arrays.asList("test1", "test2", "test3", "test4"))).anyTimes(); replay(roleService1, roleService2, roleService3, roleService4, activeRoleService, secMgr); validator = new XMLSecurityConfigValidator(secMgr); try { validator.validateRemoveRoleService(xmlConfig); //getSecurityManager().removeRoleService(xmlConfig); } catch (SecurityConfigException ex) { fail("Should work but got: " + ex.getMessage()); } xmlConfig = (XMLRoleServiceConfig) createRoleConfig("test2",XMLRoleService.class,XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE,"test2.xml"); try { validator.validateRemoveRoleService(xmlConfig); fail("non empty role service should fail"); // getSecurityManager().saveRoleService(xmlConfig); // GeoServerRoleStore store = getSecurityManager().loadRoleService("test2").createStore(); // store.addRole(GeoServerRole.ADMIN_ROLE); // store.store(); // getSecurityManager().removeRoleService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(ROLE_SERVICE_NOT_EMPTY_$1, ex.getId()); assertEquals("test2", ex.getArgs()[0]); } xmlConfig = (XMLRoleServiceConfig) createRoleConfig("test3",XMLRoleService.class,XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE, new File(getSecurityManager().role().dir(),"test3.xml").getAbsolutePath()); try { validator.validateRemoveRoleService(xmlConfig); // getSecurityManager().saveRoleService(xmlConfig); // GeoServerRoleStore store = getSecurityManager().loadRoleService("test3").createStore(); // store.addRole(GeoServerRole.ADMIN_ROLE); // store.store(); // getSecurityManager().removeRoleService(xmlConfig); } catch (SecurityConfigException ex) { fail("Should work"); } /////////////// test modify xmlConfig = (XMLRoleServiceConfig) createRoleConfig("test4",XMLRoleService.class,XMLRoleService.DEFAULT_LOCAL_ADMIN_ROLE, "testModify.xml"); XMLRoleServiceConfig oldXmlConfig = new XMLRoleServiceConfig(xmlConfig); try { xmlConfig.setValidating(true); validator.validateModifiedRoleService(xmlConfig, xmlConfig); //getSecurityManager().saveRoleService(xmlConfig); //xmlConfig.setValidating(true); //getSecurityManager().saveRoleService(xmlConfig); } catch (SecurityConfigException ex) { Assert.fail("Should work"); } try { xmlConfig.setFileName("xyz.xml"); validator.validateModifiedRoleService(xmlConfig, oldXmlConfig); fail("invalid filename change should fail"); //getSecurityManager().saveRoleService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(FILENAME_CHANGE_INVALID_$2, ex.getId()); assertEquals("testModify.xml", ex.getArgs()[0]); assertEquals("xyz.xml", ex.getArgs()[1]); } } @Test public void testUserGroupConfig() throws IOException{ super.testUserGroupConfig(); XMLUserGroupServiceConfig config = (XMLUserGroupServiceConfig) createUGConfig(XMLUserGroupService.DEFAULT_NAME, XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME,XMLConstants.FILE_UR); XMLSecurityConfigValidator validator = new XMLSecurityConfigValidator(getSecurityManager()); try { config.setName("default2"); config.setCheckInterval(-1l); validator.validateAddUserGroupService(config); fail("invalid check interval should fail"); //getSecurityManager().saveUserGroupService(config); } catch (SecurityConfigException ex) { assertEquals( CHECK_INTERVAL_INVALID,ex.getId()); assertEquals(0,ex.getArgs().length); } try { config.setCheckInterval(999l); validator.validateAddUserGroupService(config); fail("invalid check interval should fail"); //getSecurityManager().saveUserGroupService(config); } catch (SecurityConfigException ex) { assertEquals( CHECK_INTERVAL_INVALID,ex.getId()); assertEquals(0,ex.getArgs().length); } config.setCheckInterval(0); XMLUserGroupServiceConfig xmlConfig = (XMLUserGroupServiceConfig) createUGConfig("test1", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME,"test1.xml"); GeoServerUserGroup group=new GeoServerUserGroup("testgroup"); try { validator.validateAddUserGroupService(xmlConfig); //getSecurityManager().saveUserGroupService(xmlConfig); //getSecurityManager().removeUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { Assert.fail("Should work but got: " + ex.getMessage()); } XMLUserGroupServiceConfig xmlConfig5 = (XMLUserGroupServiceConfig) createUGConfig("test5", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME, "abc.xml"); try { //getSecurityManager().saveUserGroupService(xmlConfig); validator.validateAddUserGroupService(xmlConfig5); } catch (SecurityConfigException ex) { Assert.fail("Should work but got: " + ex.getMessage()); } try { xmlConfig5.setFileName(""); validator.validateAddUserGroupService(xmlConfig5); fail("empty file name should fail"); //getSecurityManager().saveUserGroupService(xmlConfig5); } catch (SecurityConfigException ex) { assertEquals(FILENAME_REQUIRED, ex.getId()); assertEquals(0, ex.getArgs().length); } // run only if a temp dir is availbale if (new XMLSecurityConfigValidator(getSecurityManager()).getTempDir()!=null) { String invalidPath="abc"+File.separator+"def.xml"; XMLUserGroupServiceConfig xmlConfig4 = (XMLUserGroupServiceConfig) createUGConfig("test4", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME, invalidPath); try { validator.validateAddUserGroupService(xmlConfig4); fail("file creation should fail"); //getSecurityManager().saveUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(FILE_CREATE_FAILED_$1, ex.getId()); assertEquals(invalidPath, ex.getArgs()[0]); } } GeoServerSecurityManager secMgr = createNiceMock(GeoServerSecurityManager.class); expect(secMgr.listAuthenticationProviders()).andReturn(new TreeSet<String>()).anyTimes(); GeoServerUserGroupService ugService1 = createNiceMock(GeoServerUserGroupService.class); expect(ugService1.getName()).andReturn("test1").anyTimes(); expect(secMgr.loadUserGroupService("test1")).andReturn(ugService1).anyTimes(); GeoServerUserGroupService ugService2 = createNiceMock(GeoServerUserGroupService.class); expect(ugService2.getName()).andReturn("test2").anyTimes(); expect(ugService2.getGroupCount()).andReturn(1).anyTimes(); expect(secMgr.loadUserGroupService("test2")).andReturn(ugService2).anyTimes(); GeoServerUserGroupService ugServiceModify = createNiceMock(GeoServerUserGroupService.class); expect(ugServiceModify.getName()).andReturn("testModify").anyTimes(); expect(secMgr.loadUserGroupService("testModify")).andReturn(ugService2).anyTimes(); expect(secMgr.listUserGroupServices()).andReturn(new TreeSet<String>( Arrays.asList("test1", "test2", "testModify"))).anyTimes(); expect(secMgr.userGroup()).andReturn(Files.asResource(tempFolder.getRoot())).anyTimes(); expect(secMgr.loadPasswordEncoder(getPlainTextPasswordEncoder().getName())) .andReturn(getPlainTextPasswordEncoder()).anyTimes(); expect(secMgr.listPasswordValidators()).andReturn( new TreeSet<String>(Arrays.asList(PasswordValidator.DEFAULT_NAME))).anyTimes(); replay(ugService1, ugService2, ugServiceModify, secMgr); //expect(secMgr.listUserGroupServices()).andReturn() validator = new XMLSecurityConfigValidator(secMgr); try { validator.validateRemoveUserGroupService(xmlConfig); //getSecurityManager().removeRoleService(xmlConfig); } catch (SecurityConfigException ex) { fail("Should work but got: " + ex.getMessage()); } xmlConfig = (XMLUserGroupServiceConfig) createUGConfig("test2", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME,"test2.xml"); try { validator.validateRemoveUserGroupService(xmlConfig); fail("non empty ug service should fail"); //getSecurityManager().saveUserGroupService(xmlConfig); //GeoServerUserGroupStore store = getSecurityManager().loadUserGroupService("test2").createStore(); //store.addGroup(group); //store.store(); //getSecurityManager().removeUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(USERGROUP_SERVICE_NOT_EMPTY_$1, ex.getId()); assertEquals("test2", ex.getArgs()[0]); } xmlConfig = (XMLUserGroupServiceConfig) createUGConfig("test3", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME, new File(getSecurityManager().userGroup().dir(),"test3.xml").getAbsolutePath()); try { validator.validateRemoveUserGroupService(xmlConfig); //getSecurityManager().saveUserGroupService(xmlConfig); //GeoServerUserGroupStore store = getSecurityManager().loadUserGroupService("test3").createStore(); //store.addGroup(group); //store.store(); //getSecurityManager().removeUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { Assert.fail("Should work but got: " + ex.getMessage()); } /////////////// test modify xmlConfig = (XMLUserGroupServiceConfig) createUGConfig("testModify", XMLUserGroupService.class, getPlainTextPasswordEncoder().getName(),PasswordValidator.DEFAULT_NAME,"testModify.xml"); XMLUserGroupServiceConfig oldXmlConfig = new XMLUserGroupServiceConfig(xmlConfig); try { xmlConfig.setValidating(true); validator.validateModifiedUserGroupService(xmlConfig, oldXmlConfig); //getSecurityManager().saveUserGroupService(xmlConfig); //xmlConfig.setValidating(true); //getSecurityManager().saveUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { Assert.fail("Should work but got: " + ex.getMessage()); } try { xmlConfig.setFileName("xyz.xml"); validator.validateModifiedUserGroupService(xmlConfig, oldXmlConfig); fail("invalid file name change should fail"); //getSecurityManager().saveUserGroupService(xmlConfig); } catch (SecurityConfigException ex) { assertEquals(FILENAME_CHANGE_INVALID_$2, ex.getId()); assertEquals("testModify.xml", ex.getArgs()[0]); assertEquals("xyz.xml", ex.getArgs()[1]); } } @Override @Test public void testAuthenticationProvider() throws IOException { super.testAuthenticationProvider(); SecurityAuthProviderConfig config = createAuthConfig("default2", UsernamePasswordAuthenticationProvider.class, null); XMLSecurityConfigValidator validator = new XMLSecurityConfigValidator(getSecurityManager()); try { //getSecurityManager().saveAuthenticationProvider(config/*, false*/); validator.validateAddAuthProvider(config); fail("no user group service should fail"); } catch (SecurityConfigException ex) { assertEquals(USERGROUP_SERVICE_REQUIRED, ex.getId()); assertEquals(0, ex.getArgs().length); } } }