Securing WebLogic JMS Resources

This is an interesting post that describes how we can secure the WebLogic JMS resources using the security policies.

By default, destinations are not protected. This means that any valid user for a WebLogic server instance can send, receive, and browse messages on a destination.  Security policies allows only users defined by the policy condition to have access control of the destination.

There are two ways of securing the JMS resources.

  1. At the JMSModule level (Group level), where a single security policy is specified for  a set of JMS resources.
  2. At the individual JMS resource level, which provides much more grained controlled over the operations that you want to secure.

Note:  If you have defined a security policy for both the JMSModule and the individual JMS Resource, the security policy of the JMS Resource would take precedence over the JMSModule security policy.

Make sure that a JMS Queue is already configured. Please follow the below post to do so.

https://weblogic-wonders.com/weblogic/2010/11/30/weblogic-jms-feature-using-a-queue/

Steps to configure security for JMS Resources.

1. Setting the security policy.

At the JMS Module Level (Group Level)

a. Login into the server console, navigate to the JMSModule.

b. Click on the Security Tab –> Policies sub tab –> Click on the Add Conditions tab to add the policy conditions.

c. From the predicate list, specify the policy conditions.

We would select the User from the drop down list for demo.

d. Specify the user who needs to have the access permissions for the JMS Module resources. Click Add –> Finish.

This completes the security policy configuration at the JMS Module level, the above configured policy is applicable for all the JMS resources under this Module unless they have their individual security policies.

The above configured policy states that the JMS resources can only be accessed by the user “weblogic”.

Security policy for a JMS Queue (Resource Level).

When you define a security policy for an individual destination on a JMS server, you can protect all operations of the destination.

a. Login into the Admin server console –> Navigate to the Queue that needs to be secured.

b. Click on the security tab –> Policies sub tab.

You can see a small drop down list, which lists the set of the operations that can be protected.

c. Click Add Conditions to add the policy conditions.

d. From the predicate list, specify the policy conditions.

We would select the User from the drop down list for demo.

e. Specify the user who needs to have the access permissions for the JMS  Queue. Click Add  –>  Finish.

This completes the security policy configuration at the JMS Queue level. Similarly you can specify policies for JMS Topic.

If you try to send a message to the Queue without having sufficient permissions , it  fails with the AccessDenied Error.

Exception in thread “Main Thread” weblogic.jms.common.JMSSecurityException: Acce

ss denied to resource: type=<jms>, application=SystemModule-0, destinationType=q

ueue, resource=Queue-0, action=send

2. Lookup Code:

In the JMS Destination lookup code, we need to pass the username and password who has the access permissions on the resource.

env.put(Context.SECURITY_PRINCIPAL, “weblogic”);
env.put(Context.SECURITY_CREDENTIALS, “weblogic”);

3. To send a  JMS message to the queue with the user credentials, execute the below QueueSend.java program.

***********************************************************************

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Hashtable;

import javax.jms.*;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class QueueSend

{

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF";

public final static String QUEUE="Queue";

private QueueConnectionFactory qconFactory;

private QueueConnection qcon;

private QueueSession qsession;

private QueueSender qsender;

private Queue queue;

private TextMessage msg;

public void init(Context ctx, String queueName)     throws NamingException, JMSException

{

qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

qcon = qconFactory.createQueueConnection();

qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

queue = (Queue) ctx.lookup(queueName);

qsender = qsession.createSender(queue);

msg = qsession.createTextMessage();

qcon.start();   }

public void send(String message) throws JMSException {

msg.setText(message);

qsender.send(msg);

}

public void close() throws JMSException {

qsender.close();

qsession.close();

qcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.queue.QueueSend WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

QueueSend qs = new QueueSend();

qs.init(ic, QUEUE);

readAndSend(qs);

qs.close();

}

private static void readAndSend(QueueSend qs)     throws IOException, JMSException

{     BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));

String line=null;

boolean quitNow = false;

do {

System.out.print("Enter message ("quit" to quit): n");

line = msgStream.readLine();

if (line != null && line.trim().length() != 0) {

qs.send(line);

System.out.println("JMS Message Sent: "+line+"n");

quitNow = line.equalsIgnoreCase("quit");

}

} while (! quitNow);

}

private static InitialContext getInitialContext(String url)     throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put(Context.SECURITY_PRINCIPAL, "weblogic");

env.put(Context.SECURITY_CREDENTIALS, "weblogic");

return new InitialContext(env);

}}

 

***********************************************************************

4. Execute the below QueueReceive.java program to receive the JMS messages.

***********************************************************************

 

import java.util.Hashtable;

import javax.jms.*;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class QueueReceive implements MessageListener

{

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF";

public final static String QUEUE="Queue";

private QueueConnectionFactory qconFactory;

private QueueConnection qcon;

private QueueSession qsession;

private QueueReceiver qreceiver;

private Queue queue;

private boolean quit = false;

public void onMessage(Message msg)

{

try {

String msgText;

if (msg instanceof TextMessage) {

msgText = ((TextMessage)msg).getText();

} else {

msgText = msg.toString();

}

System.out.println("Message Received: "+ msgText );

if (msgText.equalsIgnoreCase("quit")) {

synchronized(this) {

quit = true;

this.notifyAll(); // Notify main thread to quit

}

}

} catch (JMSException jmse) {

System.err.println("An exception occurred: "+jmse.getMessage());

}

}

public void init(Context ctx, String queueName)

throws NamingException, JMSException

{

qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

qcon = qconFactory.createQueueConnection();

qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

queue = (Queue) ctx.lookup(queueName);

qreceiver = qsession.createReceiver(queue);

qreceiver.setMessageListener(this);

qcon.start();

}

public void close()throws JMSException

{

qreceiver.close();

qsession.close();

qcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.queue.QueueReceive WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

QueueReceive qr = new QueueReceive();

qr.init(ic, QUEUE);

System.out.println("JMS Ready To Receive Messages (To quit, send a "quit" message).");

synchronized(qr) {

while (! qr.quit) {

try {

qr.wait();

} catch (InterruptedException ie) {}

}

}

qr.close();

}

private static InitialContext getInitialContext(String url)

throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put(Context.SECURITY_PRINCIPAL, "weblogic");

env.put(Context.SECURITY_CREDENTIALS, "weblogic");

return new InitialContext(env);

}

}

 

***********************************************************************

References:

http://download.oracle.com/docs/cd/E13222_01/wls/docs103/secwlres/types.html#wp1229971

Cheers,

Wonders Team. 🙂

2 comments

  1. Is there a way to setup these policies on the individual queues using WLST? I am able to setup these policies at the module level using WLST but was not successful at the queue level.

Comments are closed.