Java tutorial
/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.wso2.andes.server.security.auth.manager; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.security.Provider; import java.security.Security; import javax.security.auth.Subject; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.wso2.andes.configuration.qpid.plugins.ConfigurationPlugin; import org.wso2.andes.server.security.auth.AuthenticationResult; import org.wso2.andes.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.wso2.andes.server.security.auth.database.PlainPasswordFilePrincipalDatabase; import org.wso2.andes.server.security.auth.sasl.UsernamePrincipal; import org.wso2.andes.server.util.InternalBrokerBaseCase; /** * * Tests the public methods of PrincipalDatabaseAuthenticationManager. * */ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBaseCase { private AuthenticationManager _manager = null; // Class under test private String TEST_USERNAME = "guest"; private String TEST_PASSWORD = "guest"; /** * @see org.wso2.andes.server.util.InternalBrokerBaseCase#tearDown() */ @Override public void tearDown() throws Exception { super.tearDown(); if (_manager != null) { _manager.close(); } } /** * @see org.wso2.andes.server.util.InternalBrokerBaseCase#setUp() */ @Override public void setUp() throws Exception { super.setUp(); final String passwdFilename = createPasswordFile().getCanonicalPath(); final ConfigurationPlugin config = getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "passwordFile", passwdFilename); _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(config); } /** * Tests where the case where the config specifies a PD implementation * that is not found. */ public void testPrincipalDatabaseImplementationNotFound() throws Exception { try { _manager = PrincipalDatabaseAuthenticationManager.FACTORY .newInstance(getConfig("not.Found", null, null)); fail("Exception not thrown"); } catch (ConfigurationException ce) { // PASS } } /** * Tests where the case where the config specifies a PD implementation * of the wrong type. */ public void testPrincipalDatabaseImplementationWrongType() throws Exception { try { _manager = PrincipalDatabaseAuthenticationManager.FACTORY .newInstance(getConfig(String.class.getName(), null, null)); // Not a PrincipalDatabase implementation fail("Exception not thrown"); } catch (ConfigurationException ce) { // PASS } } /** * Tests the case where a setter with the desired name cannot be found. */ public void testPrincipalDatabaseSetterNotFound() throws Exception { try { _manager = PrincipalDatabaseAuthenticationManager.FACTORY .newInstance(getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "noMethod", "test")); fail("Exception not thrown"); } catch (ConfigurationException ce) { // PASS } } /** * QPID-1347. Make sure the exception message and stack trace is reasonable for an absent password file. */ public void testPrincipalDatabaseThrowsSetterFileNotFound() throws Exception { try { _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance( getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "passwordFile", "/not/found")); fail("Exception not thrown"); } catch (ConfigurationException ce) { // PASS assertNotNull("Expected an underlying cause", ce.getCause()); assertEquals(FileNotFoundException.class, ce.getCause().getClass()); } } /** * Tests that the PDAM registers SASL mechanisms correctly with the runtime. */ public void testRegisteredMechanisms() throws Exception { assertNotNull(_manager.getMechanisms()); // relies on those mechanisms attached to PropertiesPrincipalDatabaseManager assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms()); Provider qpidProvider = Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME); assertNotNull(qpidProvider); } /** * Tests that the SASL factory method createSaslServer correctly * returns a non-null implementation. */ public void testSaslMechanismCreation() throws Exception { SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost"); assertNotNull(server); // Merely tests the creation of the mechanism. Mechanisms themselves are tested // by their own tests. } /** * Tests that the authenticate method correctly interprets an * authentication success. * */ public void testSaslAuthenticationSuccess() throws Exception { SaslServer testServer = createTestSaslServer(true, false); AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); final Subject subject = result.getSubject(); assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest"))); assertEquals(AuthenticationStatus.SUCCESS, result.getStatus()); } /** * * Tests that the authenticate method correctly interprets an * authentication not complete. * */ public void testSaslAuthenticationNotCompleted() throws Exception { SaslServer testServer = createTestSaslServer(false, false); AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); assertNull(result.getSubject()); assertEquals(AuthenticationStatus.CONTINUE, result.getStatus()); } /** * * Tests that the authenticate method correctly interprets an * authentication error. * */ public void testSaslAuthenticationError() throws Exception { SaslServer testServer = createTestSaslServer(false, true); AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); assertNull(result.getSubject()); assertEquals(AuthenticationStatus.ERROR, result.getStatus()); } /** * Tests that the authenticate method correctly interprets an * authentication success. * */ public void testNonSaslAuthenticationSuccess() throws Exception { AuthenticationResult result = _manager.authenticate("guest", "guest"); final Subject subject = result.getSubject(); assertFalse("Subject should not be set read-only", subject.isReadOnly()); assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest"))); assertEquals(AuthenticationStatus.SUCCESS, result.getStatus()); } /** * Tests that the authenticate method correctly interprets an * authentication success. * */ public void testNonSaslAuthenticationNotCompleted() throws Exception { AuthenticationResult result = _manager.authenticate("guest", "wrongpassword"); assertNull(result.getSubject()); assertEquals(AuthenticationStatus.CONTINUE, result.getStatus()); } /** * Tests the ability to de-register the provider. */ public void testClose() throws Exception { assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms()); assertNotNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME)); _manager.close(); // Check provider has been removed. assertNull(_manager.getMechanisms()); assertNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME)); _manager = null; } /** * Test SASL implementation used to test the authenticate() method. */ private SaslServer createTestSaslServer(final boolean complete, final boolean throwSaslException) { return new SaslServer() { public String getMechanismName() { return null; } public byte[] evaluateResponse(byte[] response) throws SaslException { if (throwSaslException) { throw new SaslException("Mocked exception"); } return null; } public boolean isComplete() { return complete; } public String getAuthorizationID() { return complete ? "guest" : null; } public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException { return null; } public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException { return null; } public Object getNegotiatedProperty(String propName) { return null; } public void dispose() throws SaslException { } }; } private ConfigurationPlugin getConfig(final String clazz, final String argName, final String argValue) throws Exception { final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); XMLConfiguration xmlconfig = new XMLConfiguration(); xmlconfig.addProperty("pd-auth-manager.principal-database.class", clazz); if (argName != null) { xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.name", argName); xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.value", argValue); } // Create a CompositeConfiguration as this is what the broker uses CompositeConfiguration composite = new CompositeConfiguration(); composite.addConfiguration(xmlconfig); config.setConfiguration("security", xmlconfig); return config; } private File createPasswordFile() throws Exception { BufferedWriter writer = null; try { File testFile = File.createTempFile(this.getClass().getName(), "tmp"); testFile.deleteOnExit(); writer = new BufferedWriter(new FileWriter(testFile)); writer.write(TEST_USERNAME + ":" + TEST_PASSWORD); writer.newLine(); return testFile; } finally { if (writer != null) { writer.close(); } } } }