javajax-rsintegration-testingjaasjboss-arquillian

Tomee Embedded Adapter + Arquillian + Jax-RS - Test Jaas


I am currently having trouble testing Restful methods/paths that are secured using @RolesAllowed, these roles are pulled from the database when the user logs in through a custom JAAS LoginModule (I am able to tests those rest methods/paths that don't require any role.)

I have been stocked on this for a few days now, and have looked everywhere (specially here in SO) for answers that had lead me to where I'm now, which I will describe ahead).

I believe I will be able to log in users if I get my custom LoginModule to run on the TomEE Embedded Adapter (which is currently not).

My question is the following:

How can I set the option -Djava.security.auth.login.config=path/to/login.config" in the TomEE Embedded Adapter, in order for my custom LoginModule to be used as the JAASRealm?

I have done the following:

  1. Added to Arquillian.xml (SO is omitting <property> tags for some reason.)

     <property name="catalina_opts">
      Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.config" 
     </property>
    
  2. Added to pom.xml in the surefire plugin: (SO is omitting <argline> tags for some reason.)

     <argLine>
         -Djava.security.auth.login.config=${project.basedir}/target/test-classes/conf/test-login.config"
     </argLine>
    
  3. Added the realm in the test-server.xml and added the property in arquillian.xml

in test-server.xml

<Realm className="org.apache.catalina.realm.JAASRealm"
     appName="CustomJAASModule"
     userClassName="com.myapp.UserPrincipal, com.myapp.PasswordPrincipal"
     roleClassNames="com.myapp.RolePrincipal">
</Realm>

in arquillian.xml

<property name="serverXml">test-server.xml</property>
  1. Replaced context.xml with test-context.xml when creating the WebArchive through ShrinkWrap in the test

     @Deployment    
     public static WebArchive createDeployment() {
         WebArchive war = ShrinkWrap.create(WebArchive.class)
             .addPackages(true, Appointment.class.getPackage(), AppointmentsFacadeREST.class
             .getPackage(), ClassConstraints.class.getPackage())
             .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
             .addAsResource("users.properties")
             .addAsResource("groups.properties");
    
         war.delete("WEB-INF/web.xml");
         war.delete("WEB-INF/context.xml");
         war.addAsWebInfResource("test-web.xml", "web.xml")
             .addAsWebInfResource("test-context.xml", "context.xml")
             .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    
         return war;
     }
    

(I'm unable to format the above code for some reason, although there are 4 leading spaces in each line)

Everything runs smoothly in the regular server, I am able to debug the LoginModule and set breakpoints which work perfectly fine, the problem is just in the embedded.

I am using the following frameworks/technologies:

TomEE+ 1.7.2 (Jax-RS, OpenEJB, etc.)
JPA - OpenJPA/MySQL

Running on Ubuntu 15.04


Solution

  • I've been trying to get something like this working as well and have finally succeeded today. As for your question, you can actually put the realm configuration in your context.xml. Furthermore,the JAAS realm also allows you setting the path to the configuration file. So, you have:

    In test-context.xml, either add the following lines or replace it altogether:

    <Realm className="org.apache.catalina.realm.JAASRealm"
        appName="CustomJAASModule"
        configFile="login.config"
        userClassName="com.myapp.UserPrincipal, com.myapp.PasswordPrincipal"
        roleClassNames="com.myapp.RolePrincipal">
    </Realm>
    

    In your test class (I took the liberty of replacing some of your code with convenience methods):

    @Deployment    
    public static WebArchive createDeployment() {
        WebArchive war = ShrinkWrap.create(WebArchive.class)
            .addPackages(true, Appointment.class.getPackage(), AppointmentsFacadeREST.class
            .getPackage(), ClassConstraints.class.getPackage())
            .setWebXML("test-web.xml")
            .addAsManifestResource("test-context.xml", "context.xml")
            .addAsManifestResource("test-persistence.xml", "persistence.xml")
            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
            .addAsResource("test-login.config", "login.config")
            .addAsResource("users.properties")
            .addAsResource("groups.properties");
        return war;
    }
    

    It seems you cannot use server.xml since the classes required for the JAAS authentication need to be in ../arquillian-apache-tomee/lib/ and there is no way to add classes to that path at this time. This approach works because web.xml, context.xml and persistence.xml will take precedence over their counterparts in the container configuration.