Package org.jboss.test.security.test

Source Code of org.jboss.test.security.test.EJBSpecUnitTestCase$StressTester

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file 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.test.security.test;

import java.rmi.RemoteException;
import java.rmi.AccessException;
import java.rmi.ServerException;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.Handle;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;

import org.jboss.security.auth.login.XMLLoginConfigImpl;
import org.jboss.security.plugins.JaasSecurityManagerServiceMBean;
import org.jboss.security.SimplePrincipal;
import org.jboss.test.JBossTestCase;
import org.jboss.test.JBossTestSetup;
import org.jboss.test.security.interfaces.CalledSession;
import org.jboss.test.security.interfaces.CalledSessionHome;
import org.jboss.test.security.interfaces.StatefulSession;
import org.jboss.test.security.interfaces.StatefulSessionHome;
import org.jboss.test.security.interfaces.StatelessSession;
import org.jboss.test.security.interfaces.StatelessSessionHome;
import org.jboss.test.security.interfaces.SecurityContext;
import org.jboss.test.security.interfaces.SecurityContextHome;
import org.jboss.test.security.ejb.jbas1852.SessionFacade;
import org.jboss.test.security.ejb.jbas1852.SessionFacadeHome;
import org.jboss.test.util.AppCallbackHandler;
import org.jboss.logging.Logger;

import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestSuite;

/**
* Test of EJB spec conformace using the security-spec.jar deployment unit. These test the basic role based access
* model.
*
* @author Scott.Stark@jboss.org
* @version $Revision: 81036 $
*/
public class EJBSpecUnitTestCase extends JBossTestCase
{
   static String username = "scott";

   static char[] password = "echoman".toCharArray();

   static String QUEUE_FACTORY = "ConnectionFactory";

   LoginContext lc;

   boolean loggedIn;

   public EJBSpecUnitTestCase(String name)
   {
      super(name);
   }

   /**
    * Validate that the users have the expected logins and roles.
    *
    * @throws Exception
    */
   public void testSecurityDomain() throws Exception
   {
      log.info("+++ testSecurityDomain, domain=spec-test");
      MBeanServerConnection conn = getServer();
      ObjectName secMgrName = new ObjectName("jboss.security:service=JaasSecurityManager");
      JaasSecurityManagerServiceMBean secMgr = (JaasSecurityManagerServiceMBean) MBeanServerInvocationHandler
            .newProxyInstance(conn, secMgrName, JaasSecurityManagerServiceMBean.class, false);

      // Test the spec-test security domain
      String domain = "spec-test";
      SimplePrincipal user = new SimplePrincipal("scott");
      boolean isValid = secMgr.isValid(domain, user, password);
      assertTrue("scott password is echoman", isValid);
      HashSet testRole = new HashSet();
      testRole.add(new SimplePrincipal("Echo"));
      boolean hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has Echo role", hasRole);
      testRole.clear();
      testRole.add(new SimplePrincipal("EchoLocal"));
      hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has EchoLocal role", hasRole);
      testRole.clear();
      testRole.add(new SimplePrincipal("ProjectUser"));
      hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has ProjectUser role", hasRole);

      isValid = secMgr.isValid(domain, user, "badpass".toCharArray());
      assertTrue("badpass is an invalid password for scott", isValid == false);

      // Test the spec-test-domain security domain
      log.info("+++ testSecurityDomain, domain=spec-test-domain");
      domain = "spec-test-domain";
      isValid = secMgr.isValid(domain, user, password);
      assertTrue("scott password is echoman", isValid);
      hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has Echo role", hasRole);
      testRole.clear();
      SimplePrincipal echoLocal = new SimplePrincipal("EchoLocal");
      testRole.add(echoLocal);
      hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has EchoLocal role", hasRole);
      testRole.clear();
      SimplePrincipal projectUser = new SimplePrincipal("ProjectUser");
      testRole.add(projectUser);
      hasRole = secMgr.doesUserHaveRole(domain, user, password, testRole);
      assertTrue("scott has ProjectUser role", hasRole);
      Set roles = secMgr.getUserRoles(domain, user, password);
      assertTrue(roles != null);
      assertTrue("roles contains EchoLocal", roles.contains(echoLocal));
      assertTrue("roles contains ProjectUser", roles.contains(projectUser));

      isValid = secMgr.isValid(domain, user, "badpass".toCharArray());
      assertTrue("badpass is an invalid password for scott", isValid == false);
   }

   /**
    * Test the use of getCallerPrincipal from within the ejbCreate in a stateful session bean
    */
   public void testStatefulCreateCaller() throws Exception
   {
      log.debug("+++ testStatefulCreateCaller");
      login();
      InitialContext jndiContext = new InitialContext();
      Object obj = jndiContext.lookup("spec.StatefulSession");
      obj = PortableRemoteObject.narrow(obj, StatefulSessionHome.class);
      StatefulSessionHome home = (StatefulSessionHome) obj;
      log.debug("Found StatefulSessionHome");
      // The create should be allowed to call getCallerPrincipal
      StatefulSession bean = home.create("testStatefulCreateCaller");
      // Need to invoke a method to ensure an ejbCreate call
      bean.echo("testStatefulCreateCaller");
      log.debug("Bean.echo(), ok");

      logout();
   }

   /**
    * Test that: 1. SecureBean returns a non-null principal when getCallerPrincipal is called with a security context
    * and that this is propagated to its Entity bean ref.
    *
    * 2. UnsecureBean throws an IllegalStateException when getCallerPrincipal is called without a security context.
    */
   public void testGetCallerPrincipal() throws Exception
   {
      logout();
      log.debug("+++ testGetCallerPrincipal()");
      Object obj = getInitialContext().lookup("spec.UnsecureStatelessSession2");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found Unsecure StatelessSessionHome");
      StatelessSession bean = home.create();
      log.debug("Created spec.UnsecureStatelessSession2");

      try
      {
         // This should fail because echo calls getCallerPrincipal()
         bean.echo("Hello from nobody?");
         fail("Was able to call StatelessSession.echo");
      }
      catch (RemoteException e)
      {
         log.debug("echo failed as expected");
      }
      bean.remove();

      login();
      obj = getInitialContext().lookup("spec.StatelessSession2");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      home = (StatelessSessionHome) obj;
      log.debug("Found spec.StatelessSession2");
      bean = home.create();
      log.debug("Created spec.StatelessSession2");
      // Test that the Entity bean sees username as its principal
      String echo = bean.echo(username);
      log.debug("bean.echo(username) = " + echo);
      assertTrue("username == echo", echo.equals(username));
      bean.remove();
   }

   /**
    * Test that a call interacting with different security domains does not change the
    *
    * @throws Exception
    */
   public void testDomainInteraction() throws Exception
   {
      logout();
      login("testDomainInteraction", "testDomainInteraction".toCharArray());
      log.debug("+++ testDomainInteraction()");
      Object obj = getInitialContext().lookup("spec.UserInRoleContextSession");
      obj = PortableRemoteObject.narrow(obj, SecurityContextHome.class);
      SecurityContextHome home = (SecurityContextHome) obj;
      log.debug("Found UserInRoleContextSession");
      SecurityContext bean = home.create();
      log.debug("Created spec.UserInRoleContextSession");
      HashSet roles = new HashSet();
      roles.add("Role1");
      roles.add("Role2");
      bean.testDomainInteraction(roles);
      bean.remove();
   }

   /**
    * Test that the calling principal is propagated across bean calls.
    */
   public void testPrincipalPropagation() throws Exception
   {
      log.debug("+++ testPrincipalPropagation");
      logout();
      login();
      Object obj = getInitialContext().lookup("spec.UnsecureStatelessSession2");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found Unsecure StatelessSessionHome");
      StatelessSession bean = home.create();
      log.debug("Created spec.UnsecureStatelessSession2");
      log.debug("Bean.forward('testPrincipalPropagation') -> " + bean.forward("testPrincipalPropagation"));
      bean.remove();
   }

   /**
    * Test that the echo method is accessible by an Echo role. Since the noop() method of the StatelessSession bean was
    * not assigned any permissions it should be unchecked.
    */
   public void testMethodAccess() throws Exception
   {
      log.debug("+++ testMethodAccess");
      login();
      Object obj = getInitialContext().lookup("spec.StatelessSession");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found StatelessSessionHome");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession");
      log.debug("Bean.echo('Hello') -> " + bean.echo("Hello"));

      try
      {
         // This should not be allowed
         bean.noop();
         fail("Was able to call StatelessSession.noop");
      }
      catch (RemoteException e)
      {
         log.debug("StatelessSession.noop failed as expected");
      }
      bean.remove();
   }

   /**
    * Test that the echo method is accessible by an Echo role. Since the excluded() method of the StatelessSession bean
    * has been placed into the excluded set it should not accessible by any user. This uses the security domain of the
    * JaasSecurityDomain service to test its use as an authentication mgr.
    */
   public void testDomainMethodAccess() throws Exception
   {
      log.debug("+++ testDomainMethodAccess");
      login();
      Object obj = getInitialContext().lookup("spec.StatelessSessionInDomain");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found StatelessSessionInDomain home");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSessionInDomain");
      log.debug("Bean.echo('testDomainMethodAccess') -> " + bean.echo("testDomainMethodAccess"));

      try
      {
         // This should not be allowed
         bean.excluded();
         fail("Was able to call StatelessSession.excluded");
      }
      catch (RemoteException e)
      {
         log.debug("StatelessSession.excluded failed as expected");
      }
      bean.remove();
   }

   /**
    * Test that the permissions assigned to the stateless session bean: with
    * ejb-name=org/jboss/test/security/ejb/StatelessSession_test are read correctly.
    */
   public void testMethodAccess2() throws Exception
   {
      log.debug("+++ testMethodAccess2");
      login();
      InitialContext jndiContext = new InitialContext();
      Object obj = jndiContext.lookup("spec.StatelessSession_test");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found StatelessSessionHome");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession_test");
      log.debug("Bean.echo('testMethodAccess2') -> " + bean.echo("testMethodAccess2"));
      bean.remove();
   }

   /**
    * Test a user with Echo and EchoLocal roles can access the CalleeBean through its local interface by calling the
    * CallerBean and that a user with only a EchoLocal cannot call the CallerBean.
    */
   public void testLocalMethodAccess() throws Exception
   {
      log.debug("+++ testLocalMethodAccess");
      login();
      InitialContext jndiContext = new InitialContext();
      Object obj = jndiContext.lookup("spec.CallerBean");
      obj = PortableRemoteObject.narrow(obj, CalledSessionHome.class);
      CalledSessionHome home = (CalledSessionHome) obj;
      log.debug("Found spec.CallerBean Home");
      CalledSession bean = home.create();
      log.debug("Created spec.CallerBean");
      log.debug("Bean.invokeEcho('testLocalMethodAccess') -> " + bean.invokeEcho("testLocalMethodAccess"));
      bean.remove();
   }

   /**
    * Test access to a bean with a mix of remote interface permissions and unchecked permissions with the unchecked
    * permissions declared first.
    *
    * @throws Exception
    */
   public void testUncheckedRemote() throws Exception
   {
      log.debug("+++ testUncheckedRemote");
      login();
      Object obj = getInitialContext().lookup("spec.UncheckedSessionRemoteLast");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found UncheckedSessionRemoteLast");
      StatelessSession bean = home.create();
      log.debug("Created spec.UncheckedSessionRemoteLast");
      log.debug("Bean.echo('testUncheckedRemote') -> " + bean.echo("testUncheckedRemote"));
      try
      {
         bean.excluded();
         fail("Was able to call UncheckedSessionRemoteLast.excluded");
      }
      catch (RemoteException e)
      {
         log.debug("UncheckedSessionRemoteLast.excluded failed as expected");
      }
      bean.remove();
      logout();
   }

   /**
    * Test access to a bean with a mix of remote interface permissions and unchecked permissions with the unchecked
    * permissions declared last.
    *
    * @throws Exception
    */
   public void testRemoteUnchecked() throws Exception
   {
      log.debug("+++ testRemoteUnchecked");
      login();
      Object obj = getInitialContext().lookup("spec.UncheckedSessionRemoteFirst");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found UncheckedSessionRemoteFirst");
      StatelessSession bean = home.create();
      log.debug("Created spec.UncheckedSessionRemoteFirst");
      log.debug("Bean.echo('testRemoteUnchecked') -> " + bean.echo("testRemoteUnchecked"));
      try
      {
         bean.excluded();
         fail("Was able to call UncheckedSessionRemoteFirst.excluded");
      }
      catch (RemoteException e)
      {
         log.debug("UncheckedSessionRemoteFirst.excluded failed as expected");
      }
      bean.remove();
      logout();
   }

   /**
    * Test that a user with a role that has not been assigned any method permissions in the ejb-jar descriptor is able
    * to access a method that has been marked as unchecked.
    */
   public void testUnchecked() throws Exception
   {
      log.debug("+++ testUnchecked");
      // Login as scott to create the bean
      login();
      Object obj = getInitialContext().lookup("spec.StatelessSession");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found spec.StatelessSession Home");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession");
      // Logout and login back in as stark to test access to the unchecked method
      logout();
      login("stark", "javaman".toCharArray());
      bean.unchecked();
      log.debug("Called Bean.unchecked()");
      logout();
   }

   /**
    * Test that a user with a valid role is able to access a bean for which all methods have been marked as unchecked.
    */
   public void testUncheckedWithLogin() throws Exception
   {
      log.debug("+++ testUncheckedWithLogin");
      // Login as scott to see that a user with roles is allowed access
      login();
      Object obj = getInitialContext().lookup("spec.UncheckedSession");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found spec.StatelessSession Home");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession");
      bean.unchecked();
      log.debug("Called Bean.unchecked()");
      logout();
   }

   /**
    * Test that user scott who has the Echo role is not able to access the StatelessSession2.excluded method even though
    * the Echo role has been granted access to all methods of StatelessSession2 to test that the excluded-list takes
    * precendence over the method-permissions.
    */
   public void testExcluded() throws Exception
   {
      log.debug("+++ testExcluded");
      login();
      Object obj = getInitialContext().lookup("spec.StatelessSession2");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found spec.StatelessSession2 Home");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession2");
      try
      {
         bean.excluded();
         fail("Was able to call Bean.excluded()");
      }
      catch (Exception e)
      {
         log.debug("Bean.excluded() failed as expected");
         // This is what we expect
      }
      logout();
   }

   /**
    * This method tests the following call chains: 1. RunAsStatelessSession.echo() -> PrivateEntity.echo() 2.
    * RunAsStatelessSession.noop() -> RunAsStatelessSession.excluded() 3. RunAsStatelessSession.forward() ->
    * StatelessSession.echo() 1. Should succeed because the run-as identity of RunAsStatelessSession is valid for
    * accessing PrivateEntity. 2. Should succeed because the run-as identity of RunAsStatelessSession is valid for
    * accessing RunAsStatelessSession.excluded(). 3. Should fail because the run-as identity of RunAsStatelessSession is
    * not Echo.
    */
   public void testRunAs() throws Exception
   {
      log.debug("+++ testRunAs");
      login();
      Object obj = getInitialContext().lookup("spec.RunAsStatelessSession");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found RunAsStatelessSession Home");
      StatelessSession bean = home.create();
      log.debug("Created spec.RunAsStatelessSession");
      log.debug("Bean.echo('testRunAs') -> " + bean.echo("testRunAs"));
      bean.noop();
      log.debug("Bean.noop(), ok");

      try
      {
         // This should not be allowed
         bean.forward("Hello");
         fail("Was able to call RunAsStatelessSession.forward");
      }
      catch (RemoteException e)
      {
         log.debug("StatelessSession.forward failed as expected");
      }
      bean.remove();
   }

   /**
    * This method tests the following call chain: Level1CallerBean.callEcho() -> Level2CallerBean.invokeEcho() ->
    * Level3CalleeBean.echo() The Level1CallerBean uses a run-as of InternalRole and the Level2CallerBean and
    * Level3CalleeBean are only accessible by InternalRole.
    */
   public void testDeepRunAs() throws Exception
   {
      log.debug("+++ testDeepRunAs");
      login();
      Object obj = getInitialContext().lookup("spec.Level1CallerBean");
      obj = PortableRemoteObject.narrow(obj, CalledSessionHome.class);
      CalledSessionHome home = (CalledSessionHome) obj;
      log.debug("Found Level1CallerBean Home");
      CalledSession bean = home.create();
      log.debug("Created spec.Level1CallerBean");
      bean.callEcho();
      log.debug("Bean.callEcho() ok");
      bean.remove();

      // Make sure we cannot access Level2CallerBean remotely
      obj = getInitialContext().lookup("spec.Level2CallerBean");
      obj = PortableRemoteObject.narrow(obj, CalledSessionHome.class);
      home = (CalledSessionHome) obj;
      log.debug("Found Level2CallerBean Home");
      try
      {
         bean = home.create();
         fail("Was able to create Level2CallerBean");
      }
      catch (ServerException e)
      {
         AccessException ae = (AccessException) e.detail;
         log.debug("Caught AccessException as expected", ae);
      }
      catch (AccessException e)
      {
         log.debug("Caught AccessException as expected", e);
      }
   }

   public void testRunAsSFSB() throws Exception
   {
      log.info("+++ testRunAsSFSB");
      login();
      Object obj = getInitialContext().lookup("spec.CallerFacadeBean-testRunAsSFSB");
      obj = PortableRemoteObject.narrow(obj, CalledSessionHome.class);
      CalledSessionHome home = (CalledSessionHome) obj;
      log.debug("Found CallerFacadeBean-testRunAsSFSB Home");
      CalledSession bean = home.create();
      log.debug("Created spec.CallerFacadeBean-testRunAsSFSB");
      bean.invokeEcho("testRunAsSFSB");
      log.debug("Bean.invokeEcho() ok");
      bean.remove();
   }

   /**
    * Test the run-as side-effects raised in http://jira.jboss.com/jira/browse/JBAS-1852
    *
    * @throws Exception
    */
   public void testJBAS1852() throws Exception
   {
      log.info("+++ testJBAS1852");
      login();
      Object obj = getInitialContext().lookup("spec.PublicSessionFacade");
      obj = PortableRemoteObject.narrow(obj, SessionFacadeHome.class);
      SessionFacadeHome home = (SessionFacadeHome) obj;
      log.debug("Found PublicSessionFacade home");
      SessionFacade bean = home.create();
      log.debug("Created PublicSessionFacade");
      log.debug("Bean.callEcho('testJBAS1852') -> " + bean.callEcho("testJBAS1852"));
      bean.remove();
   }

   /**
    * Test that an MDB with a run-as identity is able to access secure EJBs that require the identity.
    */
   public void testMDBRunAs() throws Exception
   {
      log.debug("Running test testMDBRunAs");
      this.logout();
      Thread.sleep(1000);
      QueueConnectionFactory queueFactory = (QueueConnectionFactory) getInitialContext().lookup(QUEUE_FACTORY);
      Queue queA = (Queue) getInitialContext().lookup("queue/QueueA");
      Queue queB = (Queue) getInitialContext().lookup("queue/QueueB");
      QueueConnection queueConn = null;
      QueueSession session = null;
      try
      {
         queueConn = queueFactory.createQueueConnection();
         session = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
         queueConn.start();
         // create a JMS message.
         Message msg = session.createMessage();
         msg.setStringProperty("arg", "testMDBRunAs");
         msg.setJMSReplyTo(queB);
         // send the constructed message to queue A.
         QueueSender sender = session.createSender(queA);
         sender.send(msg);
         sender.close();
         log.debug("Sent msg to queue/QueueA");
         // receive the message at queue B.
         QueueReceiver recv = session.createReceiver(queB);
         msg = recv.receive(15000);
         recv.close();
         log.debug("Recv msg: " + msg);
         // get the message's content.
         String info = msg.getStringProperty("reply");
         if (info == null || info.startsWith("Failed"))
         {
            fail("Received exception reply, info=" + info);
         }
      }
      finally
      {
         if (session != null)
            session.close();
         if (queueConn != null)
            queueConn.close();
      }
   }

   /**
    * Test that an MDB with a run-as identity is able to access secure EJBs that require the identity. DeepRunAsMDB ->
    * Level1MDBCallerBean.callEcho() -> Level2CallerBean.invokeEcho() -> Level3CalleeBean.echo() The MDB uses a run-as
    * of InternalRole and the Level2CallerBean and Level3CalleeBean are only accessible by InternalRole.
    */
   public void testMDBDeepRunAs() throws Exception
   {
      log.debug("Running test testMDBDeepRunAs");
      this.logout();
      Thread.sleep(1000);
      QueueConnectionFactory queueFactory = (QueueConnectionFactory) getInitialContext().lookup(QUEUE_FACTORY);
      Queue queD = (Queue) getInitialContext().lookup("queue/QueueD");
      Queue queB = (Queue) getInitialContext().lookup("queue/QueueB");
      QueueConnection queueConn = null;
      QueueSession session = null;
      try
      {
         queueConn = queueFactory.createQueueConnection();
         session = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
         queueConn.start();
         // create a JMS message.
         Message msg = session.createMessage();
         msg.setStringProperty("arg", "testMDBDeepRunAs");
         msg.setJMSReplyTo(queB);
         // send the constructed message to queue D.
         QueueSender sender = session.createSender(queD);
         sender.send(msg);
         sender.close();
         log.debug("Sent msg to " + queD);
         // receive the message at queue B
         QueueReceiver recv = session.createReceiver(queB);
         msg = recv.receive(15000);
         recv.close();
         log.debug("Recv msg: " + msg);
         // get the message's content.
         String info = msg.getStringProperty("reply");
         if (info == null || info.startsWith("Failed"))
         {
            fail("Received exception reply, info=" + info);
         }
      }
      finally
      {
         if (session != null)
            session.close();
         if (queueConn != null)
            queueConn.close();
      }
   }

   /**
    * This method tests that the RunAsWithRolesMDB is assigned multiple roles within its onMessage so that it can call
    * into the ProjRepository session bean's methods that required ProjectAdmin, CreateFolder and DeleteFolder roles.
    */
   public void testRunAsWithRoles() throws Exception
   {
      log.debug("Running test testRunAsWithRoles");
      this.logout();
      QueueConnectionFactory queueFactory = (QueueConnectionFactory) getInitialContext().lookup(QUEUE_FACTORY);
      Queue queC = (Queue) getInitialContext().lookup("queue/QueueC");
      Queue queB = (Queue) getInitialContext().lookup("queue/QueueB");
      QueueConnection queueConn = null;
      QueueSession session = null;

      try
      {
         queueConn = queueFactory.createQueueConnection();
         session = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
         queueConn.start();
         // create a JMS message.
         Message msg = session.createMessage();
         msg.setStringProperty("name", "testRunAsWithRoles");
         msg.setJMSReplyTo(queB);
         // send the constructed message to queue C.
         QueueSender sender = session.createSender(queC);
         sender.send(msg);
         sender.close();
         log.debug("Sent msg to queue/QueueC");
         // receive the message at queue B.
         QueueReceiver recv = session.createReceiver(queB);
         msg = recv.receive(5000);
         log.debug("Recv msg: " + msg);
         recv.close();
         // get the message's content.
         String info = msg.getStringProperty("reply");
         if (info == null || info.startsWith("Failed"))
         {
            fail("Received exception reply, info=" + info);
         }
      }
      finally
      {
         if (session != null)
            session.close();
         if (queueConn != null)
            queueConn.close();
      }
   }

   /**
    * Test the security behavior of handles. To obtain secured bean from a handle that the handle be
    */
   public void testHandle() throws Exception
   {
      log.debug("+++ testHandle");
      login();
      Object obj = getInitialContext().lookup("spec.StatelessSession");
      obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
      StatelessSessionHome home = (StatelessSessionHome) obj;
      log.debug("Found StatelessSessionHome");
      StatelessSession bean = home.create();
      log.debug("Created spec.StatelessSession");
      Handle h = bean.getHandle();
      log.debug("Obtained handle: " + h);
      bean = (StatelessSession) h.getEJBObject();
      log.debug("Obtained bean from handle: " + bean);
      log.debug("Bean.echo('testHandle') -> " + bean.echo("testHandle"));
      logout();

      /*
       * Attempting to obtain the EJB fron the handle without security association present should fail
       */
      try
      {
         bean = (StatelessSession) h.getEJBObject();
         fail("Should not be able to obtain a bean without login info");
      }
      catch (Exception e)
      {
         log.debug("Obtaining bean from handle failed as expected, e=" + e.getMessage());
      }

      // One should be able to obtain a handle without a login
      h = bean.getHandle();
      login();
      // Now we should be able to obtain and use the secure bean
      bean = (StatelessSession) h.getEJBObject();
      log.debug("Obtained bean from handle: " + bean);
      log.debug("Bean.echo('testHandle2') -> " + bean.echo("testHandle2"));
      logout();
   }

   /**
    * Test the security behavior of stateful handles. To obtain secured bean from a handle requires that there be a
    * security context to obtain the ejb.
    */
   public void testStatefulHandle() throws Exception
   {
      log.debug("+++ testStatefulHandle");
      login();
      Object obj = getInitialContext().lookup("spec.StatefulSession");
      obj = PortableRemoteObject.narrow(obj, StatefulSessionHome.class);
      StatefulSessionHome home = (StatefulSessionHome) obj;
      log.debug("Found StatefulSession");
      StatefulSession bean = home.create("testStatefulHandle");
      log.debug("Created spec.StatelessSession");
      Handle h = bean.getHandle();
      log.debug("Obtained handle: " + h);
      bean = (StatefulSession) h.getEJBObject();
      log.debug("Obtained bean from handle: " + bean);
      log.debug("Bean.echo('Hello') -> " + bean.echo("Hello"));
      logout();

      /*
       * Attempting to obtain the EJB fron the handle without security association present should fail
       */
      try
      {
         bean = (StatefulSession) h.getEJBObject();
         fail("Should not be able to obtain a bean without login info");
      }
      catch (Exception e)
      {
         log.debug("Obtaining bean from handle failed as expected, e=" + e.getMessage());
      }

      // One should be able to obtain a handle without a login
      h = bean.getHandle();
      login();
      // Now we should be able to obtain and use the secure bean
      bean = (StatefulSession) h.getEJBObject();
      log.debug("Obtained bean from handle: " + bean);
      log.debug("Bean.echo('Hello') -> " + bean.echo("Hello"));
      logout();
   }

   /**
    * Stress test declarative security.
    */
   public void testStress() throws Exception
   {
      log.debug("+++ testStress");
      int count = Integer.getInteger("jbosstest.threadcount", 2).intValue();
      int iterations = 10;
      /*
       * FIXME, Use a minimum of 100 iterations iterations = Integer.getInteger("jbosstest.iterationcount",
       * 5).intValue(); if( iterations < 100 ) iterations = 100;
       */
      log.info("Creating " + count + " threads doing " + iterations + " iterations");
      Thread[] testThreads = new Thread[count];
      StressTester[] testers = new StressTester[count];

      for (int t = 0; t < count; t++)
      {
         StressTester test = new StressTester(getInitialContext(), iterations);
         testers[t] = test;
         Thread thr = new Thread(test, "Tester#" + t);
         thr.start();
         testThreads[t] = thr;
      }

      int errorCount = 0;
      for (int t = 0; t < count; t++)
      {
         Thread thr = testThreads[t];
         thr.join();
         StressTester test = testers[t];
         if (test.error != null)
         {
            errorCount++;
         }
      }
      assertTrue("Thread error count == 0", errorCount == 0);
   }

   /**
    * Stress test declarative security with the JAAS cache disabled.
    */
   public void testStressNoJaasCache() throws Exception
   {
      log.info("+++ testStressNoJaasCache, domain=spec-test");
      // Disable caching for the spec-test domain
      MBeanServerConnection conn = getServer();
      ObjectName secMgrName = new ObjectName("jboss.security:service=JaasSecurityManager");
      JaasSecurityManagerServiceMBean secMgr = (JaasSecurityManagerServiceMBean) MBeanServerInvocationHandler
            .newProxyInstance(conn, secMgrName, JaasSecurityManagerServiceMBean.class, false);
      secMgr.setCacheTimeout("spec-test", 0, 0);

      Exception failed = null;
      try
      {
         // Now execute the testStress access
         testStress();
      }
      catch (Exception e)
      {
         failed = e;
      }

      secMgr.setCacheTimeout("spec-test", 60, 60);
      if (failed != null)
         throw failed;
   }

   private static class StressTester implements Runnable
   {
      InitialContext ctx;

      int iterations;

      Throwable error;

      StressTester(InitialContext ctx, int iterations) throws Exception
      {
         this.ctx = ctx;
         this.iterations = iterations;
      }

      public void run()
      {
         Thread t = Thread.currentThread();
         Logger log = Logger.getLogger(t.getName());
         log.info("Begin run, t=" + t);
         try
         {
            AppCallbackHandler handler = new AppCallbackHandler(EJBSpecUnitTestCase.username,
                  EJBSpecUnitTestCase.password);
            for (int i = 0; i < iterations; i++)
            {
               LoginContext lc = new LoginContext("spec-test-multi-threaded", handler);
               lc.login();
               Object obj = ctx.lookup("spec.StatelessSession");
               obj = PortableRemoteObject.narrow(obj, StatelessSessionHome.class);
               StatelessSessionHome home = (StatelessSessionHome) obj;
               log.debug("Found StatelessSessionHome");
               StatelessSession bean = home.create();
               log.debug("Created spec.StatelessSession");
               log.debug("Bean.echo('Hello') -> " + bean.echo("Hello"));
               bean.remove();
               log.debug("Removed bean");
               lc.logout();
            }
         }
         catch (Throwable e)
         {
            error = e;
            log.error("Security failure", e);
         }
         log.info("End run, t=" + Thread.currentThread());
      }
   }

   /**
    * Login as user scott using the conf.name login config or 'spec-test' if conf.name is not defined.
    */
   private void login() throws Exception
   {
      login(username, password);
   }

   private void login(String username, char[] password) throws Exception
   {
      if (loggedIn)
         return;

      lc = null;
      String confName = System.getProperty("conf.name", "spec-test");
      AppCallbackHandler handler = new AppCallbackHandler(username, password);
      log.debug("Creating LoginContext(" + confName + ")");
      lc = new LoginContext(confName, handler);
      lc.login();
      log.debug("Created LoginContext, subject=" + lc.getSubject());
      loggedIn = true;
   }

   private void logout() throws Exception
   {
      if (loggedIn)
      {
         loggedIn = false;
         lc.logout();
      }
   }

   @Override
   protected void setUp() throws Exception
   {
      super.setUp();
      if (System.getProperty("java.security.auth.login.config") == null)
      {
         System.setProperty("java.security.auth.login.config", "output/resources/security/auth.conf");
      }
   }

   /**
    * Setup the test suite.
    */
   public static Test suite() throws Exception
   {
      TestSuite suite = new TestSuite();
      suite.addTest(new TestSuite(EJBSpecUnitTestCase.class));

      // Create an initializer for the test suite
      TestSetup wrapper = new JBossTestSetup(suite)
      {
         @Override
         protected void setUp() throws Exception
         {
            super.setUp();
            Configuration.setConfiguration(XMLLoginConfigImpl.getInstance());
            redeploy("security-spec.jar");
            flushAuthCache();
         }

         @Override
         protected void tearDown() throws Exception
         {
            undeploy("security-spec.jar");
            super.tearDown();

         }
      };
      return wrapper;
   }

}
TOP

Related Classes of org.jboss.test.security.test.EJBSpecUnitTestCase$StressTester

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.