/*
* JBoss, Home of Professional Open Source Copyright 2008, Red Hat Middleware
* LLC, and individual contributors by the @authors tag. See the copyright.txt
* in the distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.jboss.soa.esb.services.security.auth.login;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import junit.framework.JUnit4TestAdapter;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.services.security.SecurityConfig;
import org.jboss.soa.esb.services.security.SecurityConfigTestUtil;
import org.jboss.soa.esb.services.security.SecurityConfigUtil;
import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
import org.jboss.soa.esb.services.security.auth.AuthenticationRequestImpl;
import org.jboss.soa.esb.services.security.principals.Group;
import org.jboss.soa.esb.services.security.principals.Role;
import org.jboss.soa.esb.services.security.principals.User;
import org.jboss.soa.esb.util.ClassUtil;
import org.junit.Test;
/**
* Unit test for {@link CertificateLoginModule}
* <p/>
*
* @author <a href="mailto:dbevenius@jboss.com">Daniel Bevenius</a>
*
*/
public class CertificateLoginModuleUnitTest
{
private CertificateLoginModule module = new CertificateLoginModule();
private String keyStorePath = "certtestKeystore";
private String keyStorePassword = "storepassword";
private String keyAlias = "certtest";
@Test (expected = LoginException.class )
public void shouldThrowIfOptionsWereNull() throws LoginException
{
module.assertOptions(null);
}
@Test (expected = LoginException.class )
public void shouldThrowIfNoOptionsWereSpecified() throws LoginException
{
final HashMap<String, ?> options = new HashMap<String, Object>();
module.assertOptions(options);
}
@Test (expected = LoginException.class )
public void shouldThrowIfNoKeyStoreUrlWasSpecified() throws LoginException
{
final Map<String, Object> options = getAllOptions();
options.remove(CertificateLoginModule.KEYSTORE_URL);
module.assertOptions(options);
}
@Test (expected = LoginException.class )
public void shouldThrowIfNoKeyStorePasswordWasSpecified() throws LoginException
{
final Map<String, Object> options = getAllOptions();
options.remove(CertificateLoginModule.KEYSTORE_PASSWORD);
module.assertOptions(options);
}
@Test
public void login() throws LoginException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
final Certificate callerCert = getCertificate(keyStorePath, keyAlias);
// create the authentication request using the callers certificate as the credential
final AuthenticationRequest authRequest = getAuthenticationRequest(callerCert);
// create and setup the esb callback handler
final CertCallbackHandler certCallbackHandler = new CertCallbackHandler();
certCallbackHandler.setAuthenticationRequest(authRequest);
certCallbackHandler.setSecurityConfig(getSecurityConfig(keyAlias));
// initialize and login
final Subject subject = new Subject();
final Map<String, Object> options = getAllOptions();
options.put(CertificateLoginModule.ROLE_PROPERTIES, "roles.properties");
module.initialize(subject, certCallbackHandler, null, options);
boolean login = module.login();
assertTrue(login);
module.commit();
final Principal principal = subject.getPrincipals().iterator().next();
assertTrue(principal instanceof User);
assertEquals(principal.getName(), "Daniel Bevenius");
final Set<Group> principals = subject.getPrincipals(Group.class);
assertTrue(principals.iterator().next().isMember(new Role("worker")));
assertTrue(principals.iterator().next().isMember(new Role("esbrole")));
}
@Test (expected = LoginException.class)
public void shouldThrowIsAliasIsNotFound() throws LoginException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
final Certificate callerCert = getCertificate(keyStorePath, keyAlias);
// create the authentication request using the callers certificate as the credential
final AuthenticationRequest authRequest = getAuthenticationRequest(callerCert);
// create and setup the esb callback handler
final CertCallbackHandler certCallbackHandler = new CertCallbackHandler();
certCallbackHandler.setAuthenticationRequest(authRequest);
certCallbackHandler.setSecurityConfig(getSecurityConfig("bogusAlias"));
// initialize and login
final Subject subject = new Subject();
final Map<String, Object> options = getAllOptions();
module.initialize(subject, certCallbackHandler, null, options);
module.login();
}
@Test (expected = LoginException.class)
public void shouldThrowIfCertificateIsNull() throws LoginException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
// create the authentication request using the callers certificate as the credential
final AuthenticationRequest authRequest = getAuthenticationRequest(null);
// create and setup the esb callback handler
final CertCallbackHandler certCallbackHandler = new CertCallbackHandler();
certCallbackHandler.setAuthenticationRequest(authRequest);
certCallbackHandler.setSecurityConfig(getSecurityConfig("bogusAlias"));
// initialize and login
final Subject subject = new Subject();
final Map<String, Object> options = getAllOptions();
module.initialize(subject, certCallbackHandler, null, options);
module.login();
}
@Test (expected = LoginException.class)
public void shouldThrowIfCertifcatesDontMatch() throws LoginException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
// using a different certificate
final Certificate callerCert = getCertificate(keyStorePath, "certtest2");
// create the authentication request using the callers certificate as the credential
final AuthenticationRequest authRequest = getAuthenticationRequest(callerCert);
// create and setup the esb callback handler
final CertCallbackHandler certCallbackHandler = new CertCallbackHandler();
certCallbackHandler.setAuthenticationRequest(authRequest);
certCallbackHandler.setSecurityConfig(getSecurityConfig(keyAlias));
// initialize and login
final Subject subject = new Subject();
final Map<String, Object> options = getAllOptions();
module.initialize(subject, certCallbackHandler, null, options);
module.login();
}
@Test
public void addRoles() throws LoginException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
final Subject subject = new Subject();
final Map<String, Object> options = getAllOptions();
options.put(CertificateLoginModule.ROLE_PROPERTIES, "roles.properties");
// simulates the authenticated principal
final Principal principal = new User("Daniel Bevenius");
subject.getPrincipals().add(principal);
// call add roles
module.addRoles(subject, principal, null, options);
final Set<Group> principals = subject.getPrincipals(Group.class);
assertTrue(principals.iterator().next().isMember(new Role("worker")));
assertTrue(principals.iterator().next().isMember(new Role("esbrole")));
}
public static junit.framework.Test suite()
{
return new JUnit4TestAdapter(CertificateLoginModuleUnitTest.class);
}
private Map<String, Object> getAllOptions()
{
return getAllOptions(keyStorePath, keyStorePassword);
}
private Map<String, Object> getAllOptions(final String keystoreUrl, final String keyStorePassword)
{
HashMap<String, Object> options = new HashMap<String, Object>();
options.put(CertificateLoginModule.KEYSTORE_URL, keystoreUrl);
options.put(CertificateLoginModule.KEYSTORE_PASSWORD, keyStorePassword);
return options;
}
private Certificate getCertificate(final String keyStorePath, final String alias) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
final KeyStore keyStore = loadKeyStore(keyStorePath, keyStorePassword);
assertTrue("Keystore did not contain the expected alias : " + keyAlias, keyStore.containsAlias(alias));
return keyStore.getCertificate(alias);
}
private AuthenticationRequest getAuthenticationRequest(final Certificate callerCert)
{
// create the authentication request using the callers certificate as the credential
return new AuthenticationRequestImpl.Builder(null, Collections.singleton((Object)callerCert)).build();
}
private SecurityConfig getSecurityConfig(final String alias)
{
final ConfigTree securityFragment = SecurityConfigTestUtil.createSecurityFragment("adminRole", null, null, null, alias);
return SecurityConfigUtil.createSecurityConfig(securityFragment);
}
private KeyStore loadKeyStore(final String keyStorePath, final String keyStorePassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = ClassUtil.getResourceAsStream(keyStorePath, this.getClass());
keystore.load(in, (keyStorePassword).toCharArray());
assertNotNull("Was not able to load keystore: " + keyStorePath, keystore);
return keystore;
}
}