package org.dcache.gplazma; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import javax.security.auth.Subject; import java.security.Principal; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Properties; import java.util.Set; import org.dcache.auth.GidPrincipal; import org.dcache.auth.UidPrincipal; import org.dcache.auth.UserNamePrincipal; import org.dcache.auth.attributes.HomeDirectory; import org.dcache.auth.attributes.Restrictions; import org.dcache.auth.attributes.RootDirectory; import org.dcache.gplazma.configuration.Configuration; import org.dcache.gplazma.configuration.ConfigurationItem; import org.dcache.gplazma.configuration.ConfigurationLoadingStrategy; import org.dcache.gplazma.configuration.StaticContentConfigurationLoadingStrategy; import org.dcache.gplazma.loader.PluginXmlGenerator; import org.dcache.gplazma.loader.Utf8DataClassLoader; import org.dcache.gplazma.loader.XmlResourcePluginRepositoryFactory; import static org.dcache.gplazma.configuration.ConfigurationItemControl.*; import static org.dcache.gplazma.configuration.ConfigurationItemType.*; import static org.junit.Assert.*; /** * * @author timur */ public class GPlazmaTests { private static final String AUTH_NAME = "findPrincipals"; private static final String MAPPING_NAME="identityMap"; private static final String ACCOUNT_NAME="uidAccount"; private static final String SESSION_NAME="homeRootSession"; private static final String FAIL_NAME = "fail_all"; private static final String USER_NAME = "root"; private static final String HOME_PATH_ARG_VALUE = "/root"; private static final String ROOT_PATH_ARG_VALUE = "/"; private static final String READ_ONLY_ARG_VALUE = "true"; private static final String ROOT_UID = "0"; private static final String ROOT_GID = "0"; public static final Properties EMPTY_PROPERTIES = new Properties(); private static final ConfigurationItem AUTH_CONFIG_ITEM = new ConfigurationItem(AUTHENTICATION, REQUIRED, AUTH_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem MAPPING_CONFIG_ITEM = new ConfigurationItem(MAPPING, REQUIRED, MAPPING_NAME, EMPTY_PROPERTIES); private static ConfigurationItem ACCOUNT_CONFIG_ITEM; private static ConfigurationItem SESSION_CONFIG_ITEM; private static final ConfigurationItem FAIL_AUTH_CONFIG_ITEM = new ConfigurationItem(AUTHENTICATION, REQUIRED, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_MAPPING_CONFIG_ITEM = new ConfigurationItem(MAPPING, REQUIRED, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_ACCOUNT_CONFIG_ITEM = new ConfigurationItem(ACCOUNT, REQUIRED, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_SESSION_CONFIG_ITEM = new ConfigurationItem(SESSION, REQUIRED, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_OPTIONAL_AUTH_CONFIG_ITEM = new ConfigurationItem(AUTHENTICATION, OPTIONAL, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_OPTIONAL_MAPPING_CONFIG_ITEM = new ConfigurationItem(MAPPING, OPTIONAL, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_OPTIONAL_ACCOUNT_CONFIG_ITEM = new ConfigurationItem(ACCOUNT, OPTIONAL, FAIL_NAME, EMPTY_PROPERTIES); private static final ConfigurationItem FAIL_OPTIONAL_SESSION_CONFIG_ITEM = new ConfigurationItem(SESSION, OPTIONAL, FAIL_NAME, EMPTY_PROPERTIES); private Utf8DataClassLoader _classLoader; private PluginXmlGenerator _pluginXml; private Subject _inputSubject; private static final ConfigurationItem[] EMPTY_CONFIG_ARRAY = new ConfigurationItem[0]; private static final Configuration EMPTY_CONFIG = new Configuration(Arrays.asList(EMPTY_CONFIG_ARRAY)); @Before public void setUp() { _classLoader = new Utf8DataClassLoader(XmlResourcePluginRepositoryFactory.RESOURCE_PATH); Thread currentThread = Thread.currentThread(); currentThread.setContextClassLoader( _classLoader); Properties accountProperties = new Properties(); accountProperties.put("uid", ROOT_UID); ACCOUNT_CONFIG_ITEM = new ConfigurationItem(ACCOUNT, REQUISITE, ACCOUNT_NAME, accountProperties); Properties sessionProperties = new Properties(); sessionProperties.put(AddHomeRootSessionPlugin.USER_KEY, USER_NAME); sessionProperties.put(AddHomeRootSessionPlugin.HOME_KEY, HOME_PATH_ARG_VALUE); sessionProperties.put(AddHomeRootSessionPlugin.ROOT_KEY, ROOT_PATH_ARG_VALUE); sessionProperties.put(AddHomeRootSessionPlugin.READONLY_KEY, READ_ONLY_ARG_VALUE); SESSION_CONFIG_ITEM = new ConfigurationItem(SESSION, REQUIRED, SESSION_NAME, sessionProperties); _pluginXml = new PluginXmlGenerator(); _pluginXml.clear(); _pluginXml.addPlugin( Collections.singleton( AUTH_NAME), FindPrincipalsInCredentialsPlugin.class); _pluginXml.addPlugin( Collections.singleton( MAPPING_NAME), IdentityMappingPlugin.class); _pluginXml.addPlugin( Collections.singleton( ACCOUNT_NAME), CheckUIDAccountPlugin.class); _pluginXml.addPlugin( Collections.singleton( SESSION_NAME), AddHomeRootSessionPlugin.class); _pluginXml.addPlugin( Collections.singleton( FAIL_NAME), AlwaysFailPlugin.class); _classLoader.addResource( _pluginXml); CheckUIDAccountPlugin.reset(); //input subject _inputSubject = newTestSubject(); } /** * The authenticatie strategy will throw an exception as there are no principals * identified * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testEmptyConfigLogin() throws AuthenticationException { Subject subject = new Subject(false, Collections.<Principal>emptySet(), Collections.emptySet(), Collections.emptySet()); GPlazma instance = new GPlazma(newLoadStrategy(EMPTY_CONFIG),EMPTY_PROPERTIES); LoginReply result = instance.login(subject); Assert.assertNotNull(result); } /** * * Test of login method, of class GPlazma. * This test should succeed as we configure the four plugins in * configuration that will fill in minimally required plincipals and * attributes * <br> * First plugin is authentication type FindPrincipalsInCredentialsPlugin, * which should check both public and private credentials and find all * objects of type Principal. * <br> * Second plugin is mapping type IdentityMappingPlugin (self explanatory) * <br> * Third plugin is account type which will check that specified uid Principal * is present, otherwise it fails * It also records found uids in the static set, which we can check to verify * that is was called * <br> * And the last plugin to be called is AddHomeRootSessionPlugin that * adds home and root attributes only if certain user principal is present * */ @Test public void testLogin() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); runLoginAssertions(config); } /** * Configuration is same as above, but we add optional plugins of each type that * fail * @throws AuthenticationException */ @Test public void testLoginWithOptionalFailed() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, FAIL_OPTIONAL_AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, FAIL_OPTIONAL_MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, FAIL_OPTIONAL_ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM, FAIL_OPTIONAL_SESSION_CONFIG_ITEM); runLoginAssertions(config); } /** * Configuration is same as in testLogin, but we add required failing authentication plugin * fail * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithRequiredAuthenticationFailed() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, FAIL_AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } /** * Configuration is same as in testLogin, but we add required failing authentication plugin * fail * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithRequiredMappingFailed() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, FAIL_MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } /** * Configuration is same as in testLogin, but we add required failing authentication plugin * fail * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithRequiredAccountFailed() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, FAIL_ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } /** * Configuration is same as in testLogin, but we add required failing authentication plugin * fail * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithRequiredSessionFailed() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM, FAIL_SESSION_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } /** * Configuration is same as in testLogin, but without session * should fail in the check of presence of the home and root attributes * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithoutSession() throws AuthenticationException { //configuration Configuration config = newConfiguration ( AUTH_CONFIG_ITEM, MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } /** * Configuration is same as in testLogin, but without mapping. * @throws AuthenticationException */ @Test public void testLoginWithoutMapping() throws AuthenticationException { Configuration config = newConfiguration( AUTH_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); runLoginAssertions(config); } /** * Configuration is same as in testLogin, but without authentication * should fail in the check of presence identified principlas * @throws AuthenticationException */ @Test (expected=AuthenticationException.class) public void testLoginWithoutAuthentication() throws AuthenticationException { //configuration Configuration config = newConfiguration ( MAPPING_CONFIG_ITEM, ACCOUNT_CONFIG_ITEM, SESSION_CONFIG_ITEM); assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); Assert.assertNotNull(result); } private static Configuration newConfiguration(ConfigurationItem ... items) { return new Configuration( Arrays.asList(items)); } private static Subject newTestSubject() { //input subject Set<Object> publicCredentials = new HashSet<>(); publicCredentials.add(new UserNamePrincipal(USER_NAME)); publicCredentials.add(new UidPrincipal(ROOT_UID)); Set<Object> privateCredentials = new HashSet<>(); privateCredentials.add(new GidPrincipal(ROOT_GID,true)); return new Subject( false, Collections.<Principal>emptySet(), publicCredentials, privateCredentials); } private static ConfigurationLoadingStrategy newLoadStrategy(Configuration configuration) { return new StaticContentConfigurationLoadingStrategy(configuration); } private void runLoginAssertions(Configuration config) throws AuthenticationException { assertFalse(CheckUIDAccountPlugin.isCalled()); // do the work here LoginReply result = new GPlazma(newLoadStrategy(config), EMPTY_PROPERTIES).login(_inputSubject); // check the results assertTrue(CheckUIDAccountPlugin.isCalled()); Set<Principal> expectedPrincipals = new HashSet<>(); expectedPrincipals.add(new UserNamePrincipal(USER_NAME)); expectedPrincipals.add(new UidPrincipal(ROOT_UID)); expectedPrincipals.add(new GidPrincipal(ROOT_GID,true)); Set<Principal> resultPrincipals = result.getSubject().getPrincipals(); assertEquals(resultPrincipals, expectedPrincipals); Set<Object> expectedAttributes = new HashSet<>(); expectedAttributes.add(new HomeDirectory(HOME_PATH_ARG_VALUE)); expectedAttributes.add(new RootDirectory(ROOT_PATH_ARG_VALUE)); expectedAttributes.add(Restrictions.readOnly()); Set<Object> resultAttributes = result.getSessionAttributes(); assertEquals(expectedAttributes, resultAttributes); } }