You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2013/07/13 18:51:53 UTC

svn commit: r1502827 - in /activemq/activemq-apollo/trunk: apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/ apollo-broker/src/test/scala/ apollo-dto/src/main/java/o...

Author: chirino
Date: Sat Jul 13 16:51:53 2013
New Revision: 1502827

URL: http://svn.apache.org/r1502827
Log:
Fixes APLO-330 : Support using a different Authorizer Authenticator implementations.

Added:
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityFactory.scala
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/SecurityDTO.java
    activemq/activemq-apollo/trunk/apollo-stomp/src/test/resources/apollo-stomp-custom-security.xml
    activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/StompCustomSecurityTest.scala
    activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/UserOwnershipSecurityFactory.scala
Modified:
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/VirtualHost.scala
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/Authorizer.scala
    activemq/activemq-apollo/trunk/apollo-broker/src/test/scala/BrokerFunSuiteSupport.scala
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
    activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala Sat Jul 13 16:51:53 2013
@@ -503,13 +503,7 @@ class Broker() extends BaseService with 
       null
     }
 
-    if (config.authentication != null && config.authentication.enabled.getOrElse(true)) {
-      authenticator = new JaasAuthenticator(config.authentication, security_log)
-      authorizer=Authorizer(this)
-    } else {
-      authenticator = null
-      authorizer=Authorizer()
-    }
+    SecurityFactory.install(this)
 
     val host_config_by_id = HashMap[AsciiBuffer, VirtualHostDTO]()
     config.virtual_hosts.foreach{ value =>

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/VirtualHost.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/VirtualHost.scala?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/VirtualHost.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/VirtualHost.scala Sat Jul 13 16:51:53 2013
@@ -148,25 +148,7 @@ class VirtualHost(val broker: Broker, va
     audit_log = Option(log_category.audit).map(Log(_)).getOrElse(broker.audit_log)
     connection_log = Option(log_category.connection).map(Log(_)).getOrElse(broker.connection_log)
     console_log = Option(log_category.console).map(Log(_)).getOrElse(broker.console_log)
-
-    if (config.authentication != null) {
-      if (config.authentication.enabled.getOrElse(true)) {
-        // Virtual host has it's own settings.
-        authenticator = new JaasAuthenticator(config.authentication, security_log)
-      } else {
-        // Don't use security on this host.
-        authenticator = null
-      }
-    } else {
-      // use the broker's settings..
-      authenticator = broker.authenticator
-    }
-    if( authenticator!=null ) {
-      val rules = config.access_rules.toList ::: broker.config.access_rules.toList
-      authorizer = Authorizer(broker, this)
-    } else {
-      authorizer = Authorizer()
-    }
+    SecurityFactory.install(this)
   }
 
   override protected def _start(on_completed:Task):Unit = {

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/Authorizer.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/Authorizer.scala?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/Authorizer.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/Authorizer.scala Sat Jul 13 16:51:53 2013
@@ -102,17 +102,18 @@ object Authorizer {
     def can(ctx: SecurityContext, action: String, resource: SecuredResource) = true
   }
 
-  def apply(broker:Broker, host:VirtualHost=null):Authorizer = {
+  def apply(broker:Broker):Authorizer = {
     import collection.JavaConversions._
+    val pk = broker.authenticator.acl_principal_kinds
+    val rules = broker.config.access_rules.toList.flatMap(parse(broker.console_log, _,pk))
+    new RulesAuthorizer(version_counter.incrementAndGet(), rules.toArray )
+  }
 
-    val rules = if( host==null ) {
-      val pk = broker.authenticator.acl_principal_kinds
-      broker.config.access_rules.toList.flatMap(parse(broker.console_log, _,pk))
-    } else {
-      val pk = host.authenticator.acl_principal_kinds
-      host.config.access_rules.toList.flatMap(parse(host.console_log, _,pk, host)) :::
-      broker.config.access_rules.toList.flatMap(parse(broker.console_log, _,pk))
-    }
+  def apply(host:VirtualHost=null):Authorizer = {
+    import collection.JavaConversions._
+    val pk = host.authenticator.acl_principal_kinds
+    val rules =  host.config.access_rules.toList.flatMap(parse(host.console_log, _,pk, host)) :::
+        host.broker.config.access_rules.toList.flatMap(parse(host.broker.console_log, _,pk))
     new RulesAuthorizer(version_counter.incrementAndGet(), rules.toArray )
   }
 

Added: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityFactory.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityFactory.scala?rev=1502827&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityFactory.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityFactory.scala Sat Jul 13 16:51:53 2013
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.apollo.broker.security
+
+import org.apache.activemq.apollo.util._
+import org.apache.activemq.apollo.broker.{VirtualHost, Broker}
+
+trait SecurityFactory {
+  def install(broker:Broker):Unit
+  def install(virtual_host:VirtualHost):Unit
+}
+
+object DefaultSecurityFactory extends SecurityFactory {
+
+  def install(broker:Broker) = {
+    import OptionSupport._
+    val config = broker.config
+    if (config.authentication != null && config.authentication.enabled.getOrElse(true)) {
+      broker.authenticator = new JaasAuthenticator(config.authentication, broker.security_log)
+      broker.authorizer = Authorizer(broker)
+    } else {
+      broker.authenticator = null
+      broker.authorizer = Authorizer()
+    }
+  }
+
+  def install(host:VirtualHost) = {
+    import OptionSupport._
+    val config = host.config
+    val broker = host.broker
+
+    if (config.authentication != null) {
+      if (config.authentication.enabled.getOrElse(true)) {
+        // Virtual host has it's own settings.
+        host.authenticator = new JaasAuthenticator(config.authentication, host.security_log)
+      } else {
+        // Don't use security on this host.
+        host.authenticator = null
+      }
+    } else {
+      // use the broker's settings..
+      host.authenticator = broker.authenticator
+    }
+    if( broker.authenticator !=null ) {
+      host.authorizer = Authorizer(host)
+    } else {
+      host.authorizer = Authorizer()
+    }
+  }
+}
+
+/**
+ * <p>
+ * </p>
+ *
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ */
+object SecurityFactory extends SecurityFactory {
+
+  def install(broker: Broker) = {
+    var factory_name = broker.config.security_factory
+    if( factory_name == null ) {
+      DefaultSecurityFactory.install(broker)
+    } else {
+      val sf = ClassFinder.default_loader.load(factory_name, classOf[SecurityFactory])
+      sf.install(broker)
+    }
+  }
+
+  def install(virtual_host: VirtualHost) = {
+    var factory_name = virtual_host.broker.config.security_factory
+    if( factory_name == null ) {
+      DefaultSecurityFactory.install(virtual_host)
+    } else {
+      val sf = ClassFinder.default_loader.load(factory_name, classOf[SecurityFactory])
+      sf.install(virtual_host)
+    }
+  }
+
+}

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/test/scala/BrokerFunSuiteSupport.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/test/scala/BrokerFunSuiteSupport.scala?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/test/scala/BrokerFunSuiteSupport.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/test/scala/BrokerFunSuiteSupport.scala Sat Jul 13 16:51:53 2013
@@ -213,7 +213,7 @@ class BrokerFunSuiteSupport extends FunS
     super.afterAll()
   }
 
-  override def onTestFailure(e:Throwable) = {
+  override def onTestFailure(e:Throwable) = try {
     info("====== broker state dump start ======")
     val c = new CountDownLatch(1)
     broker.dispatch_queue {
@@ -256,6 +256,8 @@ class BrokerFunSuiteSupport extends FunS
     }
     c.await()
     info("====== broker state dump emd ======")
+  } catch {
+    case x:Throwable =>
   }
 
   def connector_port(connector: String) = BrokerTestSupport.connector_port(broker, connector)

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java Sat Jul 13 16:51:53 2013
@@ -114,6 +114,14 @@ public class BrokerDTO {
     @XmlAnyElement(lax=true)
     public List<Object> other = new ArrayList<Object>();
 
+    /**
+     * If you want use a custom authorization and authentication scheme,
+     * then set this to the name of a class that implements the
+     * SecurityFactory interface.
+     */
+    @XmlAttribute(name = "security_factory")
+    public String security_factory;
+
 
     @Override
     public boolean equals(Object o) {
@@ -128,25 +136,36 @@ public class BrokerDTO {
             return false;
         if (client_address != null ? !client_address.equals(brokerDTO.client_address) : brokerDTO.client_address != null)
             return false;
-        if (connectors != null ? !connectors.equals(brokerDTO.connectors) : brokerDTO.connectors != null) return false;
+        if (connectors != null ? !connectors.equals(brokerDTO.connectors) : brokerDTO.connectors != null)
+            return false;
+        if (id != null ? !id.equals(brokerDTO.id) : brokerDTO.id != null)
+            return false;
         if (key_storage != null ? !key_storage.equals(brokerDTO.key_storage) : brokerDTO.key_storage != null)
             return false;
         if (log_category != null ? !log_category.equals(brokerDTO.log_category) : brokerDTO.log_category != null)
             return false;
-        if (notes != null ? !notes.equals(brokerDTO.notes) : brokerDTO.notes != null) return false;
-        if (other != null ? !other.equals(brokerDTO.other) : brokerDTO.other != null) return false;
-        if (services != null ? !services.equals(brokerDTO.services) : brokerDTO.services != null) return false;
-        if (validation != null ? !validation.equals(brokerDTO.validation) : brokerDTO.validation != null) return false;
+        if (notes != null ? !notes.equals(brokerDTO.notes) : brokerDTO.notes != null)
+            return false;
+        if (other != null ? !other.equals(brokerDTO.other) : brokerDTO.other != null)
+            return false;
+        if (security_factory != null ? !security_factory.equals(brokerDTO.security_factory) : brokerDTO.security_factory != null)
+            return false;
+        if (services != null ? !services.equals(brokerDTO.services) : brokerDTO.services != null)
+            return false;
+        if (validation != null ? !validation.equals(brokerDTO.validation) : brokerDTO.validation != null)
+            return false;
         if (virtual_hosts != null ? !virtual_hosts.equals(brokerDTO.virtual_hosts) : brokerDTO.virtual_hosts != null)
             return false;
-        if (web_admins != null ? !web_admins.equals(brokerDTO.web_admins) : brokerDTO.web_admins != null) return false;
+        if (web_admins != null ? !web_admins.equals(brokerDTO.web_admins) : brokerDTO.web_admins != null)
+            return false;
 
         return true;
     }
 
     @Override
     public int hashCode() {
-        int result = notes != null ? notes.hashCode() : 0;
+        int result = id != null ? id.hashCode() : 0;
+        result = 31 * result + (notes != null ? notes.hashCode() : 0);
         result = 31 * result + (virtual_hosts != null ? virtual_hosts.hashCode() : 0);
         result = 31 * result + (connectors != null ? connectors.hashCode() : 0);
         result = 31 * result + (client_address != null ? client_address.hashCode() : 0);
@@ -158,7 +177,7 @@ public class BrokerDTO {
         result = 31 * result + (services != null ? services.hashCode() : 0);
         result = 31 * result + (validation != null ? validation.hashCode() : 0);
         result = 31 * result + (other != null ? other.hashCode() : 0);
+        result = 31 * result + (security_factory != null ? security_factory.hashCode() : 0);
         return result;
     }
-
 }
\ No newline at end of file

Added: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/SecurityDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/SecurityDTO.java?rev=1502827&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/SecurityDTO.java (added)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/SecurityDTO.java Sat Jul 13 16:51:53 2013
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.apollo.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
+
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ */
+@XmlType (name = "security_type")
+@JsonTypeInfo(use=JsonTypeInfo.Id.CUSTOM, include=JsonTypeInfo.As.PROPERTY, property="@class")
+@JsonTypeIdResolver(ApolloTypeIdResolver.class)
+@JsonIgnoreProperties(ignoreUnknown = true)
+abstract public class SecurityDTO {
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SecurityDTO)) return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return 0;
+    }
+}
\ No newline at end of file

Added: activemq/activemq-apollo/trunk/apollo-stomp/src/test/resources/apollo-stomp-custom-security.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-stomp/src/test/resources/apollo-stomp-custom-security.xml?rev=1502827&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-stomp/src/test/resources/apollo-stomp-custom-security.xml (added)
+++ activemq/activemq-apollo/trunk/apollo-stomp/src/test/resources/apollo-stomp-custom-security.xml Sat Jul 13 16:51:53 2013
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<broker xmlns="http://activemq.apache.org/schema/activemq/apollo" security_factory="org.apache.activemq.apollo.stomp.test.UserOwnershipSecurityFactory">
+
+  <authentication domain="StompSecurityTest"/>
+  <access_rule allow="connect_group" action="connect"/>
+  <access_rule allow="can_send_create_consume_queue" kind="queue" action="send create consume"/>
+  <access_rule allow="can_send_create_queue" kind="queue" action="send create"/>
+  <access_rule allow="can_send_queue"        kind="queue" action="send"/>
+  <access_rule allow="can_receive_queue"     kind="queue" action="receive"/>
+  <access_rule allow="can_consume_queue"     kind="queue" action="consume"/>
+  <access_rule allow="can_send_create_topic" kind="topic" action="send create"/>
+  <access_rule allow="can_send_topic"        kind="topic" action="send"/>
+  <access_rule allow="can_recieve_topic"     kind="topic" action="receive create"/>
+  <access_rule allow="can_consume_create_ds" kind="dsub"  action="consume create"/>
+  <access_rule allow="can_consume_ds"        kind="dsub"  action="consume"/>
+  <access_rule allow="can_recieve_topic"     kind="dsub"  action="receive create"/>
+
+  <access_rule allow="guest" action="connect"/>
+  <access_rule allow="guest" action="create destroy send receive consume" kind="topic queue dsub" id_regex="test.*"/>
+
+  <!-- only allow connects over the tcp2 connector -->
+  <access_rule allow="connector_restricted" action="connect" connector="tcp2"/>
+
+
+  <virtual_host id="default">
+    <host_name>localhost</host_name>
+  </virtual_host>
+
+  <connector id="tcp" bind="tcp://0.0.0.0:0">
+    <stomp>
+      <add_user_header kind="org.apache.activemq.jaas.UserPrincipal">JMSXUserID</add_user_header>
+      <add_user_header kind="org.apache.activemq.apollo.broker.security.SourceAddressPrincipal">sender-ip</add_user_header>
+    </stomp>
+  </connector>
+  <connector id="tcp2" bind="tcp://0.0.0.0:0">
+  </connector>
+  <connector id="stomp-udp" bind="udp://0.0.0.0:0" protocol="stomp-udp">
+    <stomp>
+      <add_user_header kind="org.apache.activemq.apollo.broker.security.SourceAddressPrincipal">sender-ip</add_user_header>
+    </stomp>
+  </connector>
+
+</broker>
\ No newline at end of file

Added: activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/StompCustomSecurityTest.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/StompCustomSecurityTest.scala?rev=1502827&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/StompCustomSecurityTest.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/StompCustomSecurityTest.scala Sat Jul 13 16:51:53 2013
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.apollo.stomp.test
+
+import java.lang.String
+import java.nio.channels.DatagramChannel
+import java.net.InetSocketAddress
+import org.fusesource.hawtbuf.AsciiBuffer
+
+class StompCustomSecurityTest extends StompTestSupport {
+
+  override def broker_config_uri: String = "xml:classpath:apollo-stomp-custom-security.xml"
+
+  override def is_parallel_test_class: Boolean = false
+
+  override def beforeAll = {
+    try {
+      val login_file = new java.io.File(getClass.getClassLoader.getResource("login.config").getFile())
+      System.setProperty("java.security.auth.login.config", login_file.getCanonicalPath)
+    } catch {
+      case x: Throwable => x.printStackTrace
+    }
+    super.beforeAll
+  }
+
+  test("User authorized to use own queues") {
+    connect("1.1", client,
+      "login:guest\n" +
+      "passcode:guest\n")
+
+    client.write(
+      "SEND\n" +
+       "destination:/queue/user.guest\n" +
+       "receipt:0\n" +
+       "\n" +
+       "Hello World\n")
+
+    wait_for_receipt("0")
+
+  }
+
+
+  test("User not authorized to use other queues") {
+    connect("1.1", client,
+      "login:guest\n" +
+      "passcode:guest\n")
+
+    client.write(
+      "SEND\n" +
+      "destination:/queue/user.hiram\n" +
+      "receipt:0\n" +
+      "\n" +
+      "Hello World\n")
+
+    val frame = client.receive()
+    frame should startWith("ERROR\n")
+    frame should include("message:Not authorized to create the queue")
+
+  }
+
+}

Added: activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/UserOwnershipSecurityFactory.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/UserOwnershipSecurityFactory.scala?rev=1502827&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/UserOwnershipSecurityFactory.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-stomp/src/test/scala/org/apache/activemq/apollo/stomp/test/UserOwnershipSecurityFactory.scala Sat Jul 13 16:51:53 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.apollo.stomp.test
+
+import org.apache.activemq.apollo.broker.security._
+import org.apache.activemq.apollo.broker.{Queue, Broker, VirtualHost}
+import java.lang.Boolean
+
+/**
+ * This is an example implementation of a SecurityFactory which
+ * provides the default authentication and authorization behaviours,
+ * except that it applies a dynamic authorization scheme so that users
+ * are only allowed to use queues named "user.${user}.**"
+ */
+class UserOwnershipSecurityFactory extends SecurityFactory {
+
+  def install(broker: Broker) {
+    DefaultSecurityFactory.install(broker)
+  }
+
+  def install(virtual_host: VirtualHost) {
+    DefaultSecurityFactory.install(virtual_host)
+    val default_authorizer = virtual_host.authorizer
+    virtual_host.authorizer = new Authorizer() {
+      def can(ctx: SecurityContext, action: String, resource: SecuredResource): Boolean = {
+        resource.resource_kind match {
+          case SecuredResource.QueueKind =>
+            val id = resource.id
+            return id.startsWith("user."+ctx.user) || id.startsWith("user."+ctx.user+".")
+          case _ =>
+            return default_authorizer.can(ctx, action, resource)
+        }
+      }
+    }
+  }
+}

Modified: activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala?rev=1502827&r1=1502826&r2=1502827&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ClassFinder.scala Sat Jul 13 16:51:53 2013
@@ -28,6 +28,7 @@ object ClassFinder extends Log {
 
   trait Loader {
     def discover[T](path:String, clazz: Class[T])( callback: List[T]=>Unit )
+    def load[T](name: String, clazz: Class[T]): T
   }
 
   case class ClassLoaderLoader(loaders: Seq[ClassLoader]) extends Loader {
@@ -54,6 +55,16 @@ object ClassFinder extends Log {
       val singltons = classes.flatMap(x=> instantiate(clazz, x) ).distinct
       callback( singltons.toList )
     }
+
+    def load[T](name: String, clazz: Class[T]): T = {
+      loaders.foreach { loader=>
+        instantiate(clazz, loader.loadClass(name)) match {
+          case Some(rc)=> return rc
+          case None =>
+        }
+      }
+      throw new ClassNotFoundException(name)
+    }
   }
 
   def instantiate[T](target:Class[T], clazz:Class[_]) = {