users@glassfish.java.net

Need some help with RunAs

From: <glassfish_at_javadesktop.org>
Date: Tue, 18 Sep 2007 20:15:28 PDT

I had originally semi-figured this out in thread 221577, but I ran into some caveats. Some background first: I have some back-end processing I need to run (reporting, specifically), and I am starting a new thread from a life cycle method (I've tried with a GenericServlet and with a context listener).

Anyway, I've placed a @RunAs("system") on my servlet, which seems to be ignored.

[b]application.xml[/b]
[code]
  <security-role>
    <description>Used for intra-container communication.</description>
    <role-name>system</role-name>
  </security-role>
[/code]


[b]sun-application.xml[/b]
[code]
  <security-role-mapping>
    <role-name>system</role-name>
    <principal-name>admin</principal-name>
    <principal-name>_system</principal-name>
  </security-role-mapping>
[/code]


[b]web.xml[/b]
[code]
    <!--
       - Asynchronous services
     -->
    <servlet>
        <description>Creates a thread to manage services within the application.</description>
        <servlet-name>Services</servlet-name>
        <servlet-class>intranet.services.ServiceServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
[/code]


[b]ReportingEJB[/b]
[code]
@Stateless
@DeclareRoles({
    "system",
    "application_reporting_admin",
    "application_reporting_read"
})
public class ReportingEJB implements IReportingEJB {
// snip
    @RolesAllowed({
        "system",
        "application_reporting_admin",
        "application_reporting_read"
    })
    public List<ReportCategory> getReportCategoryList() {
        System.out.println("Caller Principal:" + cx.getCallerPrincipal());
        System.out.println(cx.isCallerInRole("system"));
        
        // Return all report categories
        return em.createQuery("SELECT c FROM ReportCategory AS c").getResultList();
    }
// snip
}
[/code]


[b]ServiceServlet[/b]
[code]
@RunAs(value="system")
public class ServiceServlet extends GenericServlet {

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        try {
            IReportingEJB ejb = (IReportingEJB) new InitialContext().lookup("java:comp/env/ejb/ReportingEJB");
            ejb.getReportCategoryList();
        } catch (NamingException ex) {
            throw new ServletException(ex);
        }
    }
}
[/code]


[b]Log output (if called from /Service)[/b]
Caller Principal:jrod
false


[b]Log output (if called from init())[/b]
Caller Principal:admin
true

I've noticed that if I use the life cycle init-type methods, the principal is admin if I deployed my application. If glassfish deploys it for me when it starts, the caller is null:
JACC Policy Provider: PolicyWrapper.implies, context(intranet/intranet-ejb_jar)- permission((javax.security.jacc.EJBMethodPermission ReportingEJB getReportCategoryList,Local,)) domain that failed(ProtectionDomain (file:/intranet/intranet-ejb_jar <no signer certificates>)
 null
 <no principals>
 java.security.Permissions_at_1f2a8fb (
 (javax.security.auth.PrivateCredentialPermission javax.resource.spi.security.PasswordCredential * "*" read)
 (javax.management.MBeanTrustPermission register)
 (java.io.FilePermission /tmp/- delete)
 (java.io.FilePermission /home/jrod/glassfish/domains/domain1/lib/databases/- delete)
 (java.io.FilePermission <<ALL FILES>> read,write)
 (java.lang.RuntimePermission getClassLoader)
 (java.lang.RuntimePermission loadLibrary.*)
 (java.lang.RuntimePermission accessDeclaredMembers)
 (java.lang.RuntimePermission getProtectionDomain)
 (java.lang.RuntimePermission modifyThreadGroup)
 (java.lang.RuntimePermission stopThread)
 (java.lang.RuntimePermission setContextClassLoader)
 (java.lang.RuntimePermission queuePrintJob)
 (java.net.SocketPermission localhost:1024- listen,resolve)
 (java.net.SocketPermission * connect,resolve)
 (javax.management.MBeanPermission [com.sun.messaging.jms.*:*] *)
 (java.util.PropertyPermission line.separator read)
 (java.util.PropertyPermission java.vm.version read)
 (java.util.PropertyPermission java.vm.specification.version read)
 (java.util.PropertyPermission java.vm.specification.vendor read)
 (java.util.PropertyPermission java.vendor.url read)
 (java.util.PropertyPermission java.vm.name read)
 (java.util.PropertyPermission * read,write)
 (java.util.PropertyPermission os.name read)
 (java.util.PropertyPermission java.vm.vendor read)
 (java.util.PropertyPermission path.separator read)
 (java.util.PropertyPermission java.specification.name read)
 (java.util.PropertyPermission os.version read)
 (java.util.PropertyPermission os.arch read)
 (java.util.PropertyPermission java.class.version read)
 (java.util.PropertyPermission java.version read)
 (java.util.PropertyPermission file.separator read)
 (java.util.PropertyPermission java.vendor read)
 (java.util.PropertyPermission java.vm.specification.name read)
 (java.util.PropertyPermission java.specification.version read)
 (java.util.PropertyPermission java.specification.vendor read)
 (unresolved com.sun.corba.ee.impl.presentation.rmi.DynamicAccessPermission access null)
 (unresolved com.sun.enterprise.security.CORBAObjectPermission * *)
)
)
EJB5018: An exception was thrown during an ejb invocation on [ReportingEJB]
javax.ejb.AccessLocalException: Client not authorized for this invocation.

        at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1218)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:195)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:83)
        at $Proxy34.getReportCategoryList(Unknown Source)
        at intranet.services.ServiceServlet.init(ServiceServlet.java:60)
        at javax.servlet.GenericServlet.init(GenericServlet.java:254)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1178)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1007)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4800)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:5188)
        at com.sun.enterprise.web.WebModule.start(WebModule.java:327)
        at com.sun.enterprise.web.LifecycleStarter.doRun(LifecycleStarter.java:58)
        at com.sun.appserv.management.util.misc.RunnableBase.runSync(RunnableBase.java:296)
        at com.sun.appserv.management.util.misc.RunnableBase._submit(RunnableBase.java:168)
        at com.sun.appserv.management.util.misc.RunnableBase.submit(RunnableBase.java:184)
        at com.sun.enterprise.web.VirtualServer.startChildren(VirtualServer.java:1672)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1231)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:955)
        at com.sun.enterprise.web.LifecycleStarter.doRun(LifecycleStarter.java:58)
        at com.sun.appserv.management.util.misc.RunnableBase.runSync(RunnableBase.java:296)
        at com.sun.appserv.management.util.misc.RunnableBase.run(RunnableBase.java:330)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
        at java.lang.Thread.run(Thread.java:619)
...Snipped a bunch of repeating exceptions...



So my ultimate question is, how do you get RunAs to work properly on a servlet? Documentation seems to be scant. It might be worthwhile to note that I'm using an ldap realm, and the user [b]does not[/b] exist in the realm, I would like to avoid creating this user if I can since I only want this to be a glassfish meta-user of sorts.
[Message sent by forum member 'jeffreyrodriguez' (jeffreyrodriguez)]

http://forums.java.net/jive/thread.jspa?messageID=235935