You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@activemq.apache.org by bhartsb <bh...@cox.net> on 2006/08/10 13:35:36 UTC

Security and restricting access

I want to restrict all topic/queue creation to a) a few admin users with
usernames and passwords, and b) specific applications that will authenticate
programatically using a username and password.  

I've read some of the posts, plus I've looked at
http://incubator.apache.org/activemq/security.html

I have not found yet a simple example of how to accomplish what I'm asking.

Per the ActiveMQ security information I have several problems with it and or
comments:

1)  In the beginning it mentions: "a default authorization mechanism using a
simple XML configuration file.   Where is the example of this?  There is an
example given below on the same page but it seems to be for JAAS.  

2)  If one were to use JAAS, where is SIMPLE information on how JAAS
cohabitates/integrates/installs with ActiveMQ?  Something like an overview
would be really nice!  JAAS seems like it has a pretty substantial learning
curve associated with it.  It is painfull to have to spend an inordinate
amount of time reading and familiarizing just to do something as simple as
what I've described.

3)  The sample code and files given on the page, really seem to assume lots
of prior background knowlege of the reader, and the page is mostly
unintelligible to a newbie.

Hope someone can shed some light.

Thanks.
-- 
View this message in context: http://www.nabble.com/Security-and-restricting-access-tf2084128.html#a5742527
Sent from the ActiveMQ - User forum at Nabble.com.


Re: Security and restricting access

Posted by bhartsb <bh...@cox.net>.
Thanks for your help.


ENP wrote:
> 
>> Some specific explaination, per your code would be nice.  Like what steps
>> you
>> are doing, and how it works with the ActiveMQ plugin model.  I've never
>> used
>> Spring.  I've never used a plugin.  I understand fundamental core Java,
>> period.  
>> 
>> The basic security model I was envisioning using was to have the
>> topic/queue
>> names include a UUID...if one doesn't know the queue name, including
>> UUID,
>> then one can't access the queue.    The client is C++.  The backend
>> logic,
>> per my project, is done with JAVA Servlets/Struts, and a set of tables in
>> a
>> MySQL DB.
>> 
>> As I stated originally, I want to be able to only have a few "entities",
>> authenticated by Username and Password, be able to Create and Destroy
>> Topics
>> and Queues.  Either manually or programmatically.
>> 
>> For example how could I set ActiveMQ up so that only two specific
>> usernames
>> and passwords would give topic/queue create/destroy access? 
> 
> You need to write you own class extends BrokerPluginSupport class. Such 
> classes defined as plugins for ActiveMQ broker will intercept all events 
> in broker lifecycle, so you can read event parameters (username and 
> password for example) and allow this event by calling super. or restrict 
> them by raising exception.
> 
> For defining plugins for ActiveMQ broker you need read more about 
> ActiveMQ xml configuration in 
> http://activemq.com/site/xml-configuration.html
> 
> Next you need to select raw Spring or XBeans Spring configuration 
> manner. In first case you can write this simple configuration:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
> "http://www.springframework.org/dtd/spring-beans.dtd">
> <beans>	
> 	<bean id="broker" class="org.apache.activemq.broker.BrokerService" 
> init-method="start" destroy-method="stop">
>                  <property name="brokerName" value="m0"/>
>                  <property name="persistent" value="true"/>
>                  <property name="transportConnectorURIs">
>                          <list>
>                                  <value>tcp://localhost:5000</value>
>                          </list>
>                  </property>
>                  <property name="plugins">
>                          <list>
>                                  <bean class="SimplePlugin"/>
>                          </list>
>                  </property>
>          </bean>
> </beans>
> 
> For starting this configuration (it can be named "context" by Spring 
> users) you need to write and run this class:
> 
> import org.springframework.context.support.AbstractApplicationContext;
> import
> org.springframework.context.support.FileSystemXmlApplicationContext;
> 
> public class Startup {
> 
>          public static void main(String[] args) throws 
> InterruptedException {
> 
>                  AbstractApplicationContext ctx =
>                          new FileSystemXmlApplicationContext(new String 
> []{"context.xml"});
>                  ctx.registerShutdownHook();
>                  Thread.sleep(Long.MAX_VALUE);
>          }
> 
> }
> 
> So, broker will work until pressing Ctl+C
> 
> Also you need to write class SimplePlugin extends BrokerPluginSupport 
> and overrides some of it's methods.
> 
> XBeans Spring configuration is used by default and in this case you 
> don't need write you own Startup class and can use 
> activemq.sh/activemq.bat. In this case plugins connecting described in 
> http://activemq.com/site/security.html
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Security-and-restricting-access-tf2084128.html#a5780036
Sent from the ActiveMQ - User forum at Nabble.com.


Re: Security and restricting access

Posted by bhartsb <bh...@cox.net>.
Thanks.


ENP wrote:
> 
>> Some specific explaination, per your code would be nice.  Like what steps
>> you
>> are doing, and how it works with the ActiveMQ plugin model.  I've never
>> used
>> Spring.  I've never used a plugin.  I understand fundamental core Java,
>> period.  
>> 
>> The basic security model I was envisioning using was to have the
>> topic/queue
>> names include a UUID...if one doesn't know the queue name, including
>> UUID,
>> then one can't access the queue.    The client is C++.  The backend
>> logic,
>> per my project, is done with JAVA Servlets/Struts, and a set of tables in
>> a
>> MySQL DB.
>> 
>> As I stated originally, I want to be able to only have a few "entities",
>> authenticated by Username and Password, be able to Create and Destroy
>> Topics
>> and Queues.  Either manually or programmatically.
>> 
>> For example how could I set ActiveMQ up so that only two specific
>> usernames
>> and passwords would give topic/queue create/destroy access? 
> 
> You need to write you own class extends BrokerPluginSupport class. Such 
> classes defined as plugins for ActiveMQ broker will intercept all events 
> in broker lifecycle, so you can read event parameters (username and 
> password for example) and allow this event by calling super. or restrict 
> them by raising exception.
> 
> For defining plugins for ActiveMQ broker you need read more about 
> ActiveMQ xml configuration in 
> http://activemq.com/site/xml-configuration.html
> 
> Next you need to select raw Spring or XBeans Spring configuration 
> manner. In first case you can write this simple configuration:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
> "http://www.springframework.org/dtd/spring-beans.dtd">
> <beans>	
> 	<bean id="broker" class="org.apache.activemq.broker.BrokerService" 
> init-method="start" destroy-method="stop">
>                  <property name="brokerName" value="m0"/>
>                  <property name="persistent" value="true"/>
>                  <property name="transportConnectorURIs">
>                          <list>
>                                  <value>tcp://localhost:5000</value>
>                          </list>
>                  </property>
>                  <property name="plugins">
>                          <list>
>                                  <bean class="SimplePlugin"/>
>                          </list>
>                  </property>
>          </bean>
> </beans>
> 
> For starting this configuration (it can be named "context" by Spring 
> users) you need to write and run this class:
> 
> import org.springframework.context.support.AbstractApplicationContext;
> import
> org.springframework.context.support.FileSystemXmlApplicationContext;
> 
> public class Startup {
> 
>          public static void main(String[] args) throws 
> InterruptedException {
> 
>                  AbstractApplicationContext ctx =
>                          new FileSystemXmlApplicationContext(new String 
> []{"context.xml"});
>                  ctx.registerShutdownHook();
>                  Thread.sleep(Long.MAX_VALUE);
>          }
> 
> }
> 
> So, broker will work until pressing Ctl+C
> 
> Also you need to write class SimplePlugin extends BrokerPluginSupport 
> and overrides some of it's methods.
> 
> XBeans Spring configuration is used by default and in this case you 
> don't need write you own Startup class and can use 
> activemq.sh/activemq.bat. In this case plugins connecting described in 
> http://activemq.com/site/security.html
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Security-and-restricting-access-tf2084128.html#a5780036
Sent from the ActiveMQ - User forum at Nabble.com.


Re: Security and restricting access

Posted by Eugene Prokopiev <pr...@stc.donpac.ru>.
> Some specific explaination, per your code would be nice.  Like what steps you
> are doing, and how it works with the ActiveMQ plugin model.  I've never used
> Spring.  I've never used a plugin.  I understand fundamental core Java,
> period.  
> 
> The basic security model I was envisioning using was to have the topic/queue
> names include a UUID...if one doesn't know the queue name, including UUID,
> then one can't access the queue.    The client is C++.  The backend logic,
> per my project, is done with JAVA Servlets/Struts, and a set of tables in a
> MySQL DB.
> 
> As I stated originally, I want to be able to only have a few "entities",
> authenticated by Username and Password, be able to Create and Destroy Topics
> and Queues.  Either manually or programmatically.
> 
> For example how could I set ActiveMQ up so that only two specific usernames
> and passwords would give topic/queue create/destroy access? 

You need to write you own class extends BrokerPluginSupport class. Such 
classes defined as plugins for ActiveMQ broker will intercept all events 
in broker lifecycle, so you can read event parameters (username and 
password for example) and allow this event by calling super. or restrict 
them by raising exception.

For defining plugins for ActiveMQ broker you need read more about 
ActiveMQ xml configuration in 
http://activemq.com/site/xml-configuration.html

Next you need to select raw Spring or XBeans Spring configuration 
manner. In first case you can write this simple configuration:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>	
	<bean id="broker" class="org.apache.activemq.broker.BrokerService" 
init-method="start" destroy-method="stop">
                 <property name="brokerName" value="m0"/>
                 <property name="persistent" value="true"/>
                 <property name="transportConnectorURIs">
                         <list>
                                 <value>tcp://localhost:5000</value>
                         </list>
                 </property>
                 <property name="plugins">
                         <list>
                                 <bean class="SimplePlugin"/>
                         </list>
                 </property>
         </bean>
</beans>

For starting this configuration (it can be named "context" by Spring 
users) you need to write and run this class:

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Startup {

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

                 AbstractApplicationContext ctx =
                         new FileSystemXmlApplicationContext(new String 
[]{"context.xml"});
                 ctx.registerShutdownHook();
                 Thread.sleep(Long.MAX_VALUE);
         }

}

So, broker will work until pressing Ctl+C

Also you need to write class SimplePlugin extends BrokerPluginSupport 
and overrides some of it's methods.

XBeans Spring configuration is used by default and in this case you 
don't need write you own Startup class and can use 
activemq.sh/activemq.bat. In this case plugins connecting described in 
http://activemq.com/site/security.html


Re: Security and restricting access

Posted by bhartsb <bh...@cox.net>.
Some specific explaination, per your code would be nice.  Like what steps you
are doing, and how it works with the ActiveMQ plugin model.  I've never used
Spring.  I've never used a plugin.  I understand fundamental core Java,
period.  

The basic security model I was envisioning using was to have the topic/queue
names include a UUID...if one doesn't know the queue name, including UUID,
then one can't access the queue.    The client is C++.  The backend logic,
per my project, is done with JAVA Servlets/Struts, and a set of tables in a
MySQL DB.

As I stated originally, I want to be able to only have a few "entities",
authenticated by Username and Password, be able to Create and Destroy Topics
and Queues.  Either manually or programmatically.

For example how could I set ActiveMQ up so that only two specific usernames
and passwords would give topic/queue create/destroy access? 






Most of my queues willl be specific to 





ENP wrote:
> 
> Hi,
> 
> You need to download activemq-jaas-*.jar separately for using JAAS. All 
> configuration files from 
> http://incubator.apache.org/activemq/security.html works fine with it.
> 
> I implemented my custom security for 2 user groups stored in database 
> without JAAS:
> 
> msg_producers - can write to messages.input
> msg_consumers - can read from messages.output.{$username}
> msg_dispatchers - can move messages from messages.input to
> messages.output.*
> 
> Spring context.xml looks like:
> 
> <beans>
> ...
> 	<bean id="broker" class="org.apache.activemq.broker.BrokerService" 
> init-method="start" destroy-method="stop">
>                  ...
> 		<property name="plugins">
>                          <list>
>                                  <bean 
> class="manager.broker.AuthenticationPlugin">
>                                  <property name="userManager" 
> ref="userManager"/>
>                              </bean>
>                              <bean 
> class="manager.broker.AuthorizationPlugin"/>
>                          </list>
>                  </property>
>          </bean>
> 	<bean id="userManager" class="manager.broker.UserManager">
>                  <property name="sessionFactory" 
> ref="hibernateSessionFactory"/>
>          </bean>
> ...
> </beans>
> 
> manager.broker.AuthenticationPlugin.java looks like:
> 
> public class AuthenticationPlugin extends BrokerPluginSupport {
> 
>          private Log log = LogFactory.getLog(getClass());
> 
>          private UserManagerAuth userManager;
> 
>          public void setUserManager(UserManagerAuth auth) {
>                  this.userManager = auth;
>          }
> 
>          public void addConnection(ConnectionContext context, 
> ConnectionInfo info) throws Exception {
>                  final Set<String> principals = userManager.getUserGroups(
>                          info.getUserName(),
>                  info.getPassword());
>                  if (principals == null) {
>                          String message = "User ["+info.getUserName()+"] 
> not authenticated";
>                          log.info(message);
>                          throw new SecurityException(message);
>                  } else {
>                          log.info("User ["+info.getUserName()+"] 
> connected");
>                          SecurityContext securityContext = new 
> SecurityContext(info.getUserName()) {
>                  public Set<String> getPrincipals() {
>                      return principals;
>                  }
>              };
>              context.setSecurityContext(securityContext);
>              super.addConnection(context, info);
>                  }
>          }
> 
>          public void removeConnection(ConnectionContext context, 
> ConnectionInfo info, Throwable error) throws Exception {
>                  log.info("User ["+info.getUserName()+"] disconnected");
>                  context.setSecurityContext(null);
>                  super.removeConnection(context, info, error);
>          }
> }
> 
> manager.broker.AuthorizationPlugin.java looks like:
> 
> public class AuthorizationPlugin extends BrokerPluginSupport {
> 
>          private Log log = LogFactory.getLog(getClass());
> 
>          public Destination addDestination(ConnectionContext context, 
> ActiveMQDestination destination) throws Exception {
>                  String username = 
> context.getSecurityContext().getUserName();
>                  Set principals = 
> context.getSecurityContext().getPrincipals();
>                  if (destination.isTemporary() &&
>  
> ((ActiveMQTempDestination)destination).getConnectionId().
>                          equals(context.getConnectionId().getValue())) {
>                          log.info("Destination 
> ["+destination.getQualifiedName()+"] created");
>                          return super.addDestination(context,
> destination);
>                  } else if (principals.contains("msg_dispatcher") &&
>  
> (destination.getQualifiedName().startsWith("topic://ActiveMQ.Advisory.Producer.Queue.messages.output.")) 
> ||
>  
> (destination.getQualifiedName().startsWith("topic://ActiveMQ.Advisory.Consumer.Queue.messages.output.")) 
> ||
>  
> (destination.getQualifiedName().startsWith("queue://messages.output."))) {
>                          log.info("Creating 
> ["+destination.getQualifiedName()+"] by dispatcher ["+username+"]");
>                          return super.addDestination(context,
> destination);
>                  } else if (principals.contains("msg_consumer") &&
>  
> (destination.getQualifiedName().equals("topic://ActiveMQ.Advisory.Producer.Queue.messages.output."+username)) 
> ||
>  
> (destination.getQualifiedName().equals("topic://ActiveMQ.Advisory.Consumer.Queue.messages.output."+username)) 
> ||
>  
> (destination.getQualifiedName().equals("queue://messages.output."+username))) 
> {
>                          log.info("Creating 
> ["+destination.getQualifiedName()+"] by consumer ["+username+"]");
>                          return super.addDestination(context,
> destination);
>                  } else {
>                          exceptionLog("User ["+username+"] not allowed 
> to create ["+destination.getQualifiedName()+"]");
>                          return null;
>                  }
>          }
> 
>          public Subscription addConsumer(ConnectionContext context, 
> ConsumerInfo info) throws Exception {
>                  String destination = 
> info.getDestination().getQualifiedName();
>                  String username = 
> context.getSecurityContext().getUserName();
>                  Set principals = 
> context.getSecurityContext().getPrincipals();
>                  if 
> (destination.equals("topic://ActiveMQ.Advisory.TempQueue,topic://ActiveMQ.Advisory.TempTopic")) 
> {
>                          log.info("Consumer ["+username+"] connected to 
> advisory topics");
>                          return super.addConsumer(context, info);
>                  } else if (principals.contains("msg_consumer") && 
> destination.equals("queue://messages.output."+username)) {
>                          log.info("Consumer ["+username+"] connected to 
> ["+destination+"]");
>                          return super.addConsumer(context, info);
>                  } else if (principals.contains("msg_dispatcher") && 
> destination.equals("queue://messages.input")) {
>                          log.info("Consumer ["+username+"] connected to 
> ["+destination+"]");
>                          return super.addConsumer(context, info);
>                  } else {
>                          exceptionLog("Consuming from ["+destination+"] 
> not allowed to user ["+username+"]");
>                          return null;
>                  }
>          }
> 
>          public void addProducer(ConnectionContext context, ProducerInfo 
> info) throws Exception {
>                  String destination = 
> info.getDestination().getQualifiedName();
>                  String username = 
> context.getSecurityContext().getUserName();
>                  Set principals = 
> context.getSecurityContext().getPrincipals();
>                  if 
> (destination.equals("topic://ActiveMQ.Advisory.TempQueue,topic://ActiveMQ.Advisory.TempTopic")) 
> {
>                          log.info("Producer ["+username+"] connected to 
> advisory topics");
>                          super.addProducer(context, info);
>                  } else if (principals.contains("msg_producer") && 
> destination.equals("queue://messages.input")) {
>                          log.info("Producer ["+username+"] connected to 
> ["+destination+"]");
>                          super.addProducer(context, info);
>                  } else if (principals.contains("msg_dispatcher") && 
> destination.startsWith("queue://messages.output.")) {
>                          log.info("Producer ["+username+"] connected to 
> ["+destination+"]");
>                          super.addProducer(context, info);
>                  } else {
>                          exceptionLog("Producing to ["+destination+"] 
> not allowed to user ["+username+"]");
>                  }
>          }
> 
>          public void send(ConnectionContext context, Message message) 
> throws Exception {
>                  String username = 
> context.getSecurityContext().getUserName();
>                  Set principals = 
> context.getSecurityContext().getPrincipals();
>                  Object messageObject;
>                  try {
>                          messageObject = 
> ((ActiveMQObjectMessage)message).getObject();
>                          if ((principals.contains("msg_producer") || 
> principals.contains("msg_dispatcher")) &&
>                                  messageObject instanceof 
> manager.messages.model.Message) {
>                                  log.info("User ["+username+"] sent 
> message ["+message+"]");
>                                  super.send(context, message);
>                          } else {
>                                  exceptionLog("User ["+username+"] not 
> allowed to send messages");
>                          }
>                  } catch (RuntimeException e) {
>                          exceptionLog("Only object messages allowed to 
> send");
>                  }
>          }
> 
>          private void exceptionLog(String error) {
>                  log.info(error);
>                  throw new SecurityException(error);
>          }
> 
> }
> 
> My code works only with last snapshots (not 4.0.1 release) because some 
> bugs are exists in release.
> 
> Hope this helps
> 
> --
> Eugene Prokopiev
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Security-and-restricting-access-tf2084128.html#a5747780
Sent from the ActiveMQ - User forum at Nabble.com.


Re: Security and restricting access

Posted by Eugene Prokopiev <pr...@stc.donpac.ru>.
Hi,

You need to download activemq-jaas-*.jar separately for using JAAS. All 
configuration files from 
http://incubator.apache.org/activemq/security.html works fine with it.

I implemented my custom security for 2 user groups stored in database 
without JAAS:

msg_producers - can write to messages.input
msg_consumers - can read from messages.output.{$username}
msg_dispatchers - can move messages from messages.input to messages.output.*

Spring context.xml looks like:

<beans>
...
	<bean id="broker" class="org.apache.activemq.broker.BrokerService" 
init-method="start" destroy-method="stop">
                 ...
		<property name="plugins">
                         <list>
                                 <bean 
class="manager.broker.AuthenticationPlugin">
                                 <property name="userManager" 
ref="userManager"/>
                             </bean>
                             <bean 
class="manager.broker.AuthorizationPlugin"/>
                         </list>
                 </property>
         </bean>
	<bean id="userManager" class="manager.broker.UserManager">
                 <property name="sessionFactory" 
ref="hibernateSessionFactory"/>
         </bean>
...
</beans>

manager.broker.AuthenticationPlugin.java looks like:

public class AuthenticationPlugin extends BrokerPluginSupport {

         private Log log = LogFactory.getLog(getClass());

         private UserManagerAuth userManager;

         public void setUserManager(UserManagerAuth auth) {
                 this.userManager = auth;
         }

         public void addConnection(ConnectionContext context, 
ConnectionInfo info) throws Exception {
                 final Set<String> principals = userManager.getUserGroups(
                         info.getUserName(),
                 info.getPassword());
                 if (principals == null) {
                         String message = "User ["+info.getUserName()+"] 
not authenticated";
                         log.info(message);
                         throw new SecurityException(message);
                 } else {
                         log.info("User ["+info.getUserName()+"] 
connected");
                         SecurityContext securityContext = new 
SecurityContext(info.getUserName()) {
                 public Set<String> getPrincipals() {
                     return principals;
                 }
             };
             context.setSecurityContext(securityContext);
             super.addConnection(context, info);
                 }
         }

         public void removeConnection(ConnectionContext context, 
ConnectionInfo info, Throwable error) throws Exception {
                 log.info("User ["+info.getUserName()+"] disconnected");
                 context.setSecurityContext(null);
                 super.removeConnection(context, info, error);
         }
}

manager.broker.AuthorizationPlugin.java looks like:

public class AuthorizationPlugin extends BrokerPluginSupport {

         private Log log = LogFactory.getLog(getClass());

         public Destination addDestination(ConnectionContext context, 
ActiveMQDestination destination) throws Exception {
                 String username = 
context.getSecurityContext().getUserName();
                 Set principals = 
context.getSecurityContext().getPrincipals();
                 if (destination.isTemporary() &&
 
((ActiveMQTempDestination)destination).getConnectionId().
                         equals(context.getConnectionId().getValue())) {
                         log.info("Destination 
["+destination.getQualifiedName()+"] created");
                         return super.addDestination(context, destination);
                 } else if (principals.contains("msg_dispatcher") &&
 
(destination.getQualifiedName().startsWith("topic://ActiveMQ.Advisory.Producer.Queue.messages.output.")) 
||
 
(destination.getQualifiedName().startsWith("topic://ActiveMQ.Advisory.Consumer.Queue.messages.output.")) 
||
 
(destination.getQualifiedName().startsWith("queue://messages.output."))) {
                         log.info("Creating 
["+destination.getQualifiedName()+"] by dispatcher ["+username+"]");
                         return super.addDestination(context, destination);
                 } else if (principals.contains("msg_consumer") &&
 
(destination.getQualifiedName().equals("topic://ActiveMQ.Advisory.Producer.Queue.messages.output."+username)) 
||
 
(destination.getQualifiedName().equals("topic://ActiveMQ.Advisory.Consumer.Queue.messages.output."+username)) 
||
 
(destination.getQualifiedName().equals("queue://messages.output."+username))) 
{
                         log.info("Creating 
["+destination.getQualifiedName()+"] by consumer ["+username+"]");
                         return super.addDestination(context, destination);
                 } else {
                         exceptionLog("User ["+username+"] not allowed 
to create ["+destination.getQualifiedName()+"]");
                         return null;
                 }
         }

         public Subscription addConsumer(ConnectionContext context, 
ConsumerInfo info) throws Exception {
                 String destination = 
info.getDestination().getQualifiedName();
                 String username = 
context.getSecurityContext().getUserName();
                 Set principals = 
context.getSecurityContext().getPrincipals();
                 if 
(destination.equals("topic://ActiveMQ.Advisory.TempQueue,topic://ActiveMQ.Advisory.TempTopic")) 
{
                         log.info("Consumer ["+username+"] connected to 
advisory topics");
                         return super.addConsumer(context, info);
                 } else if (principals.contains("msg_consumer") && 
destination.equals("queue://messages.output."+username)) {
                         log.info("Consumer ["+username+"] connected to 
["+destination+"]");
                         return super.addConsumer(context, info);
                 } else if (principals.contains("msg_dispatcher") && 
destination.equals("queue://messages.input")) {
                         log.info("Consumer ["+username+"] connected to 
["+destination+"]");
                         return super.addConsumer(context, info);
                 } else {
                         exceptionLog("Consuming from ["+destination+"] 
not allowed to user ["+username+"]");
                         return null;
                 }
         }

         public void addProducer(ConnectionContext context, ProducerInfo 
info) throws Exception {
                 String destination = 
info.getDestination().getQualifiedName();
                 String username = 
context.getSecurityContext().getUserName();
                 Set principals = 
context.getSecurityContext().getPrincipals();
                 if 
(destination.equals("topic://ActiveMQ.Advisory.TempQueue,topic://ActiveMQ.Advisory.TempTopic")) 
{
                         log.info("Producer ["+username+"] connected to 
advisory topics");
                         super.addProducer(context, info);
                 } else if (principals.contains("msg_producer") && 
destination.equals("queue://messages.input")) {
                         log.info("Producer ["+username+"] connected to 
["+destination+"]");
                         super.addProducer(context, info);
                 } else if (principals.contains("msg_dispatcher") && 
destination.startsWith("queue://messages.output.")) {
                         log.info("Producer ["+username+"] connected to 
["+destination+"]");
                         super.addProducer(context, info);
                 } else {
                         exceptionLog("Producing to ["+destination+"] 
not allowed to user ["+username+"]");
                 }
         }

         public void send(ConnectionContext context, Message message) 
throws Exception {
                 String username = 
context.getSecurityContext().getUserName();
                 Set principals = 
context.getSecurityContext().getPrincipals();
                 Object messageObject;
                 try {
                         messageObject = 
((ActiveMQObjectMessage)message).getObject();
                         if ((principals.contains("msg_producer") || 
principals.contains("msg_dispatcher")) &&
                                 messageObject instanceof 
manager.messages.model.Message) {
                                 log.info("User ["+username+"] sent 
message ["+message+"]");
                                 super.send(context, message);
                         } else {
                                 exceptionLog("User ["+username+"] not 
allowed to send messages");
                         }
                 } catch (RuntimeException e) {
                         exceptionLog("Only object messages allowed to 
send");
                 }
         }

         private void exceptionLog(String error) {
                 log.info(error);
                 throw new SecurityException(error);
         }

}

My code works only with last snapshots (not 4.0.1 release) because some 
bugs are exists in release.

Hope this helps

--
Eugene Prokopiev