Weblogic JMS Security Issues - A possible resolution

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Weblogic JMS Security Issues - A possible resolution

David MacDonald
Hello all,

I've been attempting to use Camel/Spring JMS with Weblogic Server (10.3.6) JMS destinations and it works just fine without secure destinations, but using secure destinations results in the exception:
weblogic.jms.common.JMSSecurityException: Access denied to resource: type=<jms>, application=jms_module, destinationType=queue, resource=jms_response, action=receive

It appears that others in the Camel/Spring community have had similar issues (e.g. here). Since there was no reasonable solution to this problem I did some research and created a new thread factory that creates Threads with the passed-in Runnable.run proxied through a Weblogic secured PrivilegedAction. The task executor for Camel and Spring JMS listeners is modified to use the new task factory to ensure all subscribing threads are 'privileged'.

I've provided some code on github with an example/test of publishing and subscribing to a secure WebLogic JMS destination using both Camel and Spring Stand-alone. Hopefully someone else in the Camel/Spring community benefits from this (and feedback is welcome!) - we needed Camel to do some things that Oracle Service Bus just isn't cut out for and the inability to use secure destination was a big blocker.

Cheers,
David
Reply | Threaded
Open this post in threaded view
|

Re: Weblogic JMS Security Issues - A possible resolution

gquintana
Hi,

I struggled against this one as well (I am happy not to be alone!), it's more related to WebLogic and Spring's DefaultMessageListenerContainer than Camel. My understanding is that, in WebLogic, the security context (who is sending/receiving messages) is bound to the thread getting the ConnectionFactory, instead of being bound to the Connection/Session object itself. With Spring DMLC, the thread getting the connection factory is not the thread sending/receiving messages, as a result we are loosing user rights between threads. I ended up with a solution based a decoratorconnectionfactory (see honeybunny post http://forum.springsource.org/showthread.php?62373-weblogic-10-standalone-jms-client ) and disabling all connection caching: each thread gets his own connectionfactory. It's a catastrophe from a performance point of view because the connectionfactory/connection can not be cached and shared between listener threads, but it works.

Your Github article is very interesting (thanks for sharing), I ignored these Security/Authenticate WebLogic classes.

I need to test the behaviour of the new SJMS component (not based on Spring DMLC) and see if it's better. We could put up WeblogicMQ specific component (based on JMS or SJMS) do solve this problem.

I advise you to read these blogs in case you didn't
http://www.jayway.com/2011/06/26/secure-jms-spring-and-weblogic-a-one-click-workaround/
http://sleeplessinslc.blogspot.fr/2009/04/weblogic-jms-standalone-multi-threaded.html

Another challenge I had to face was receiving JMS message from one broker, processing it, and then sending it to another broker. I had to introduce a Thread EIP in the middle just to lose this damned thread bound security context (user are different on both ends).
Reply | Threaded
Open this post in threaded view
|

Re: Weblogic JMS Security Issues - A possible resolution

David MacDonald
Hi,

Yeah I saw most of those pages but none were particularly satisfactory.

I didn't spend too much time on the solution of publishing to JMS from Camel because I haven't needed to use it in any real environment. Publishing to two different environments certainly throws a spanner in the works for my solution... I avoided any threading changes because I was concerned about its affect on transactions.

Ideally you would use a Delegate Processor where you would intercept calls to the JMS endpoint and would override the process method with an implementation that does the privileged action and calls processNext(...). However there's no easy way to do this in Camel (it would be nice to have an intercept(DelegateProcessor) DSL component). You could also take a look at the interceptSendToEndpoint code, and copy/paste a lot of this code such that you can wrap the call to the endpoint process method wrapped in the privileged action; I avoided this because I'm allergic to too much copy/pasting. An ideal solution would be along the lines of:
interceptSendToEndpoint("jms:*").delegateProcess(weblogicSecurityProcessor).

Cheers,
David
Reply | Threaded
Open this post in threaded view
|

Re: Weblogic JMS Security Issues - A possible resolution

gquintana
Hi David,

I don't understand why you say "I avoided any threading changes because I was concerned about its affect on transactions. " because this is actually what you're doing in WeblogicSecurityBean#runPrivilegedActionAsSubject: this piece of code is pushing/poping the security context in the threadlocal.

I don't understand either why I would need DelegateProcessor, your WeblogicSecurityInterceptStrategy seems enough.

To summarize you work (correct me if I'm wrong):
- For Inbound JMS: you're creating a dedicated thread pool with the specialized WeblogicSecureThreadFactory, as result each listener thread has his security context properly set on creation. I would just fear this security context gets dirty with time. Ideally we should intercept inside the message polling loop and wrap the MessageConsumer#receive in a runPrivilegedAction, but the DMLC is not very configurable here.
- For Outbound JMS: you're intercepting the JMS Producer Endpoint to set the security context.

Reply | Threaded
Open this post in threaded view
|

Re: Weblogic JMS Security Issues - A possible resolution

David MacDonald
Hiya,

So runPrivilegedActionAsSubject maintains the same thread. Using the thread EIP used new threads, and there was a warning on the Camel documentation page that new threads would cause issues for Spring transactions, so I avoided this route (although not thoroughly researched).

So for Inbound JMS, I don't believe the security context can get dirtied (from the perspective of listening to a JMS destination) because the same subject is used each time as soon as the thread gets started, and applies for the lifetime of the thread but I think I see where you're coming from in terms of thread re-use and sending to another foreign destination, and this could very well be a problem. The BEA/Oracle documentation recommended to wrap a privilegedAction around the code in the main method, so maybe not. I avoided wrapping the MessageConsumer#receive method because it seemed to go against the grain of what the security architecture was trying to achieve.

The Outbound JMS is a bit uncouth... the privilegedAction gets set around *every* processor which is inefficient and will break if you're going to be sending to foreign destinations. In that case you might well copy/paste the interceptSendToEndpoint code and ensure that you wrap the process call in the runPrivilegedActionAsSubject (this is probably the ideal solution).

I'm not really an expert in this, and the use-case you have involving multiple security realms introduces some issues... there's certainly an aspect of over-architecture here with respect to the security model.

Cheers,
David
Reply | Threaded
Open this post in threaded view
|

Re: Weblogic JMS Security Issues - A possible resolution

gquintana
Thanks David. It's crystal clear now.