html
iphone
ajax
database
linux
ruby-on-rails
regex
mysql
objective-c
multithreading
eclipse
silverlight
flash
perl
facebook
oracle
apache
php5
api
dom
In JBoss, the security system is not enabled on EJB3 beans if you have not set a <security-domain> value in jboss.xml. Here is a reminder for JBoss7 and it is also relevant for JBoss 6.1.
<security-domain>
jboss.xml
An alternate option is to use the proprietary annotation @org.jboss.ejb3.annotation.SecurityDomain with the proper domain value on your EJB3 beans.
@org.jboss.ejb3.annotation.SecurityDomain
According to this forum thread, a deployment descriptor WEB-INF/jboss-ejb3.xml is required when deploying EJBs in a WAR file and here is an example for it:
WEB-INF/jboss-ejb3.xml
<?xml version="1.0"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:s="urn:security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1" impl-version="2.0"> <assembly-descriptor> <s:security> <ejb-name>*</ejb-name> <s:security-domain>yourSecurityDomain</s:security-domain> </s:security> </assembly-descriptor> </jboss:ejb-jar>
Thanks Yves Martin for the suggestion. I have tried adding the jboss.xml and ejb-jar.xml as you suggested, unfortunately it didn't work.
I examined the code again and again, and finally I have found a solution to this problem. My original code set up is as follow:
ObjectRepository interface:
public interface ObjectRepository<T extends DomainObject> { public T save(T object); ... }
TaskServiceBeanLocal interface:
@Local public interface TaskServiceBeanLocal extends ObjectRepository<Task> { }
Task EJB:
@Stateless @LocalBinding(jndiBinding = TaskServiceBean.LOOKUP_STRING) @SecurityDomain(value = Security.DOMAIN) @DeclareRoles({ Roles.ADMIN, Roles.CLERK, Roles.READ_ONLY }) //By default, allow no one access, we'll enable access at the method level @RolesAllowed({}) public class TaskServiceBean implements TaskServiceBeanLocal { public static final String LOOKUP_STRING = "TaskServiceBean/local"; @RolesAllowed({ Roles.ADMIN, Roles.CLERK }) @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public Task save(Task task) { ... } }
The Arquillian failed to access the TaskServiceBean.save() method with the error as in the question:
TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] Exception:Insufficient method permissions, principal=myuser, ejbName=SecureServiceBean, method=save, interface=Local, requiredRoles=Roles(), principalRoles=Roles(Admin,)
From the TRACE logging, the requiredRoles() is empty for unknown reason. I tested by implementing a different method to the TaskServiceBeanLocal and the TaskServiceBean with the same permission:
@Local public interface TaskServiceBeanLocal extends ObjectRepository<Task> { public void test(); } //and implement the test() method, having the same permission as the save() method. public class TaskServiceBean implements TaskServiceBeanLocal { @RolesAllowed({ Roles.ADMIN, Roles.CLERK }) @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public Task save(Task task) { ... } @RolesAllowed({ Roles.ADMIN, Roles.CLERK }) @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void test() { System.out.println("hello"); } }
To my surprise, testing the test() method was successful. So I then redeclare the save() method in the interface:
@Local public interface TaskServiceBeanLocal extends ObjectRepository<Task> { public Task save(Task object); public void test(); }
Now, testing the save() method was successful. In the TRACE logging statement, I can see my requiredRoles are fully populated in the method signature.
13:44:35,399 TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] method=public au.com.infomedix.harvey.humantask.domain.Task au.com.infomedix.harvey.ejb.TaskServiceBean.save(au.com.infomedix.harvey.humantask.domain.Task), interface=Local, requiredRoles=Roles(Clerk,Admin,)
My guess is that Arquillian did not inject the security information for the generic method signature, but honestly I don't fully understand that.
Anyhow, re-declaring the method in the interface fixes the problem. Arquillian can access my secured EJB now. Thanks everyone for your valuable inputs.
-- Linh