JBoss 7 and Ejb remote call with security

This article describes my tests with ejb and JBoss7.

 

For my test a have ear (TestEar) with one ejb module (TestEjb) and one bean (TestBean).

 

TestEar.ear
   +---TestEjb.ejb
       +--mates.test.TestBean.class
          mates.test.TestBeanRemote.class

 

As security I use RealmUsersRoles with

x-users.properties

testX=test1234

x-roles.properties

testX=bean

 

And now standalone.xml

and I changed ApplicationRealm

<security-realm name="ApplicationRealm">
     <authentication>
          <jaas name="bean-sec-domain"/>
     </authentication>
</security-realm>

and security domain

 

<security-domain name="bean-sec-domain" cache-type="default">     
     <authentication>
          <login-module code="Remoting" flag="optional">
               <module-option name="password-stacking" value="useFirstPass"/>
          </login-module>
          <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
               <module-option name="defaultUsersProperties" value="file:/${jboss.server.config.dir}/x-users.properties"/>
               <module-option name="defaultRolesProperties" value="file:/${jboss.server.config.dir}/x-roles.properties"/>
               <module-option name="usersProperties" value="file:/${jboss.server.config.dir}/x-users.properties"/>
               <module-option name="rolesProperties" value="file:/${jboss.server.config.dir}/x-roles.properties"/>
               <module-option name="password-stacking" value="useFirstPass"/>
          </login-module>
     </authentication>
</security-domain>

 

And now lets look at bean.

 

@Stateless
@DeclareRoles("bean")
public class TestBean implements TestBeanRemote {

        @Resource
        private EJBContext context;

        @Override
        @RolesAllowed("bean")
        public String getName ()
        {
                return getNameFree();
        }

        @Override
        public String getNameFree ()
        {
                String aName = "";
                if (context.getCallerPrincipal() != null) {
                        aName = context.getCallerPrincipal().getName();
                }
                return "name " + aName + " " + context.isCallerInRole("bean");
        }
}

 

Let's secure EJB

add jboss-app.xml to TestEar.ear\META-INF. I use security domain other to ensure that i secure all beans.

 

<?xml version="1.0" encoding="UTF-8"?>
<p:jboss-app xmlns:p="http://www.jboss.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee ../../xsd/jboss-app_7_0.xsd ">
    <security-domain>other</security-domain>
</p:jboss-app>

 

And I want to secure TestBean. I have to add jboss-ejb3.xml to TestEjb.jar\META-INF\. TestBean is secured by bean-sec-domain.

 

<?xml version="1.0" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="urn:security" version="3.1" impl-version="2.0">
    <assembly-descriptor xmlns="http://java.sun.com/xml/ns/javaee">
        <security:security xmlns:security="urn:security">
            <security:security-domain>bean-sec-domain</security:security-domain>
            <ejb-name>TestBean</ejb-name>
        </security:security>
    </assembly-descriptor>
</jboss:ejb-jar>

 

 

Remote interface is real simple with 2 methods.

 

Client:

 

Hashtable<String, Object> p = new Hashtable<String, Object>();
p.put(Context.INITIAL_CONTEXT_FACTORY, InitialContextFactory.class.getName());
p.put(Context.PROVIDER_URL, "remote://127.0.0.1:4447/");
p.put(InitialContext.SECURITY_PRINCIPAL, "testX");
p.put(InitialContext.SECURITY_CREDENTIALS, "test1234");
p.put("jboss.naming.client.ejb.context", true);
p.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");

InitialContext c = new InitialContext(p);
TestBeanRemote vLookup = (TestBeanRemote) c.lookup("java:/TestEar/TestEjb/TestBean!"+ TestBeanRemote.class.getName());

System.out.println("x" + vLookup.getNameFree());
System.out.println("x" + vLookup.getName());

 

After this you can see

 

xname testX true
xsecured name testX true

 

That's all.

 

And now some other tests:

Most important mart is

p.put("jboss.naming.client.ejb.context", true);

without this property you will see "No EJB receiver available for handling [appName:TestEar,modulename:TestEjb,distinctname:] combination"

 

when you put in class path file jboss-ejb-client.properties with standard

 

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=x1

remote.connection.x1.host=127.0.0.1
remote.connection.x1.port = 4447
remote.connection.x1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.x1.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false  


and comment p.put("jboss.naming.client.ejb.context", true);

and in console is now

 

xname $local false
Exception in thread "main" javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public abstract java.lang.String mates.test.TestBeanRemote.getName() of bean: TestBean is not allowed

 

jboss.naming.client.ejb.context setup EJBContext on client side. See org.jboss.naming.remote.client.InitialContextFactory