Skip to main content

Security Identity Propogation for Servlet with @RunAs

9 replies [Last post]
joelstewart
Offline
Joined: 2009-11-19
Points: 0

On Glassfish 3.1 b43.
I have two applications, an EAR with EJB modules, and a separate WAR module.
When setting up security, both the EAR and the WAR use the same realm. Authenticated User subjects are propagated from the WAR to the EAR as expected. In an EJB, I can access the caller principal and check is caller in role.
Now I am trying to write some system code for startup in the WAR. I write a Servlet and annotate it with @RunAs("System") with hopes the code in the init() method will propagate as a System Role to the EJBs. I would think all I would have to do is declare the security role in the web.xml, and declare a mapping to a group in the sun specific, so I put in web.xml:
<security-role>
<description/>
<role-name>System</role-name>
</security-role>
and add to sun-web.xml:
<security-role-mapping>
<role-name>System</role-name>
<principal-name>systemuser</principal-name>
</security-role-mapping>

<servlet>
<servlet-name>StartupServlet</servlet-name>
<principal-name>systemuser</principal-name>
</servlet>
as explained here http://java.sun.com/developer/technicalArticles/J2EE/security_annotation/
This deploys, but does not propagate the identity I configured here. It propogates ANONYMOUS.
Are there other glassfish configs I need to make this work?
I've tried adding the System group and systemuser to the database, but that did nothing.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

On 16/03/11 6:02 PM, forums@java.net wrote:
> On Glassfish 3.1 b43.
>
> I have two applications, an EAR with EJB modules, and a separate WAR
> module.
>
> When setting up security, both the EAR and the WAR use the same realm.
> Authenticated User subjects are propagated from the WAR to the EAR as
> expected. In an EJB, I can access the caller principal and check is
> caller
> in role.
>
> Now I am trying to write some system code for startup in the WAR. I
> write
> a Servlet and annotate it with @RunAs("System") with hopes the code in
> the
> init() method
Did you mean the init() method of the servlet here ?. I will need to
check with the Spec people if this is a Bug. From the Servlet 3.0 spec
and JSR 250 spec it is not very clear if this should have worked.
Although by common sense since you placed the annotation on the class it
should probably apply to init().

Will check and get back.

regards,
kumar

> will propagate as a System Role to the EJBs. I would think
> all I would have to do is declare the security role in the web.xml, and
> declare a mapping to a group in the sun specific, so I put in web.xml:
>
>
>
> System
>
>
> and add to sun-web.xml:
>
>
> System
> systemuser
>
>
> StartupServlet
> systemuser
>
>
> as explained here
> http://java.sun.com/developer/technicalArticles/J2EE/security_annotation/
>
> This deploys, but does not propagate the identity I configured here. It
> propogates ANONYMOUS.
>
> *Are there other glassfish configs I need to make this work?*
>
> I've tried adding the System group and systemuser to the database, but
> that
> did nothing.
>
>
>
>
>
>

joelstewart
Offline
Joined: 2009-11-19
Points: 0

Yes, here is the servlet code:

 @RunAs(&quot;System&quot;)
public class SomeStartupServlet extends HttpServlet
{

    @EJB
    ISomeBean controller = null;

    public void init() throws ServletException
    {
    //calls to controller methods to don't propogate
joelstewart
Offline
Joined: 2009-11-19
Points: 0

On 3.0.1 (build 22) this exact deployment works sometimes. Sometimes on startup, it does not propagate. But on redeployment of the WAR it will. This is the exact same copy of the WAR.

monzillo
Offline
Joined: 2004-05-08
Points: 0

the runAs role has been declared, a non-group principal has been mapped to the role, and an appropriate runas principal (from the role) has been set on the StartupServlet; this should be more than sufficient to establish the run as identity of the servlet.

fwiw, depending on the contents of the role mapping, steps 1 and 2 may be sufficient to cause the Glassfish deployment system to select a run-as principal.

imo, the effect of runas during servlet initialization is not explicitly prescribed by the servlet spec, and I would not be surprised if Glassfish only establishes runas during the invocation of a service method of the servlet. You can confirm that your run as config is working for the more typical case, by moving your ejb call into a service method (e.g.; doGet).
I was surprised to read that runas sometimes works for you during init. we will have to look into why that might be.
it probably makes sense for the servlet spec to require that a runas designation be in effect during init (modulo the jsr 250 annotation overriding semantics). in that case, the init time run as identity of servlets configured to run as their caller, would need to be specified (presumably as undefined or unauthenticated).

Since runas is specified for a servlet, I would not expect runas to apply during context initialization; such as when ejbs are called from servlet context initializers.

Ron

joelstewart
Offline
Joined: 2009-11-19
Points: 0

Although the spec does not spell out that init() should be run with the runas identity, I would expect it would.
Because Sevlet.init() is called after @PostConstruct, and after the ServletContext is initialized (ServletContextListener.contextInitialized). Also (In Glassfish) an EJB that is @Startup @Singleton and @RunAs will properly delegate the identity to calls made in @PostConstruct.
If a Servlet cannot use init() to call injected EJBs with an identity, then what is the mechanism by which code can be run at Web App Startup and assume an identity? It is not satisfying to say it cannot.

mvatkina
Offline
Joined: 2005-04-04
Points: 0

According to the EJB spec, the @PostConstruct lifecycle callback interceptor methods execute in an unspecified security context....
-marina

joelstewart
Offline
Joined: 2009-11-19
Points: 0

Thanks for pointing this out, it is important to discuss this fully.
Section 17.6.5 Security Methods in EJBContext says that the container must provide a security context when calling a bean's business methods.
The spec also says that RunAs does not change the context for the bean that declares RunAs, but it is the Identity it passes in the security context it passes to other beans that it calls.
So, in the Example App I uploaded with the bug report, the Singleton Startup Bean's PostConstruct method does not access SecurityContext methods, but calls another Beans business methods. The only way to allow this and be true to the spec would be to create a security context with the Identity I declared in the Startup Beans' RunAs.
Glassfish does work properly in the case of the Singleton Startup, but not the Servlet.init

monzillo
Offline
Joined: 2004-05-08
Points: 0

I agree. I took a closer look at the spec, and I found the following ( in Apendex 8).
Clarification: "run-as" identity must apply to all calls from a servlet including init() and destroy() (12.7)

I can't find any such clarification in the section 12.7 or in the security chapter, so the clarification may have been
lost, but the appendix clearly notes the intent
imv, if this is not happening under a proper configiuration and use of the @RunAs annotation, then it is a bug in the RI.
please file an issue if you have not done so already, and the security team should fix this.
Ron
ps: I include the following mostly for others who may come upon this thread...
please note that when a run-as identity is set by annotation, the annotation has no effect on methods inherited from a superclass (such as init() and destory()) unless those methods are declared (i.e., overridden) in the servlet implementation class.

joelstewart
Offline
Joined: 2009-11-19
Points: 0

Bug has been submitted:
http://java.net/jira/browse/GLASSFISH-16236
Thanks.