Recently I was working with for a company to harden their set up of Active MQ. Though not the ultimate monitoring solution for Avtive MQ, they wanted to use the web console for providing some kind of ad hoc visibility on key properties. The ActiveMQ web page describes the set up that is pretty straight forward when an external servlet engine is used, but configuring the embedded jetty is a bit different.
From the 
ActiveMQ web console documentation we could see that we need 3 things:
 - An User Realm that can be plugged into the Jetty engine.
 
 - Credentials definitions.
 
 - A security aware web application.
 
Let's have a look at each of these things: 
We start with rewriting the jetty bean definition in the default activemq.xml with the following activemq.xml:
 <!--     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. --> <beans   xmlns="http://www.springframework.org/schema/beans"   xmlns:amq="http://activemq.apache.org/schema/core"   xmlns:jetty="http://mortbay.com/schemas/jetty/1.0"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd     http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">       <!-- Allows us to use system properties as variables in this configuration file -->     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">          <property name="locations">             <value>file:///${activemq.base}/conf/credentials.properties</value>          </property>          </bean>       <broker xmlns="http://activemq.apache.org/schema/core" brokerName="TRT_INT" dataDirectory="${activemq.base}/data">           <!-- Destination specific policies using destination names or wildcards -->         <destinationPolicy>             <policyMap>                 <policyEntries>                     <policyEntry queue=">" producerFlowControl="true"/>                     <policyEntry topic=">" producerFlowControl="true"/>                 </policyEntries>             </policyMap>         </destinationPolicy>                                 <!-- Define Virtual Destinations for Topics -->                 <!-- All topics will have a corresponding queue corresponding to the name pattern below                      where consumers can connect to in order to act as subscription groups. -->                 <destinationInterceptors>                   <virtualDestinationInterceptor>                     <virtualDestinations>                           <virtualTopic name=">" prefix="VTopic.*." />                         </virtualDestinations>                   </virtualDestinationInterceptor>                 </destinationInterceptors>                                 <!-- predefine Queues corresponding to Virtual topics so that no messages get lost due                      to unregistered consumers. -->             <destinations>                   <!-- The Subscriber group App1 is the name of a queue that ALL instances of App1                        would use to consume messages from the topic "X". All                            consumers using the same queue name act as ONE subscriber and the messages                            will be load balanced across the group. -->                   <!-- queue physicalName="VTopic.App1.X" / -->                 </destinations>           <!-- Use the following to configure how ActiveMQ is exposed in JMX -->         <managementContext>             <managementContext createConnector="true"/>         </managementContext>           <!-- The store and forward broker networks ActiveMQ will listen to -->         <networkConnectors>             <!-- by default just auto discover the other brokers -->             <!--<networkConnector name="default-nc" uri="multicast://default"/>-->             <!-- Example of a static configuration:             <networkConnector name="host1 and host2" uri="static://(tcp://host1:61616,tcp://host2:61616)"/>             -->         </networkConnectors>                   <!-- Using the Kaha DB store for persistence now -->         <persistenceAdapter>             <kahaDB directory="${activemq.base}/data/kahadb" />         </persistenceAdapter>                   <!-- Don't have ssl         <sslContext>             <sslContext keyStore="file:${activemq.base}/conf/broker.ks" keyStorePassword="password" trustStore="file:${activemq.base}/conf/broker.ts" trustStorePassword="password"/>         </sslContext -->           <!--  The maximum about of space the broker will use before slowing down producers -->         <systemUsage>             <systemUsage>                 <memoryUsage>                     <memoryUsage limit="350 mb"/>                 </memoryUsage>                 <storeUsage>                     <storeUsage limit="20 gb" name="foo"/>   <!-- used for persistent messages -->                 </storeUsage>                 <tempUsage>                     <tempUsage limit="100 mb"/>    <!-- used for non persistent messages -->                 </tempUsage>             </systemUsage>         </systemUsage>             <!-- The transport connectors ActiveMQ will listen to -->         <transportConnectors>             <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>         </transportConnectors>     </broker>     <jetty:jetty>     <connectors>       <jetty:nioConnector port="8161"/>         </connectors>         <handlers>       <jetty:webAppContext contextPath="/admin" resourceBase="${activemq.base}/webapps/admin" logUrlOnStart="true"/>         </handlers>         <userRealms>       <bean class="org.mortbay.jetty.security.HashUserRealm">         <property name="name" value="ActiveMQ Realm" />         <property name="config" value="${activemq.base}/conf/webconsole.properties" />       </bean>         </userRealms>   </jetty:jetty> </beans> 
  | 
Next you need to create the file webconsole.properties in the conf directory of ActiveMQ.The file contains one line per user with the format
 useName: password, [roleName]* 
  | 
For example: 
 myAdmin: THESECRET, amqAdmin 
  | 
Finally you need to amend the web.xml files of the ActiveMQ web applications (${activemq.base}/webapps/*/WEB-INF/web.xml) with the following xml fragment:
 <security-constraint>   <web-resource-collection>     <web-resource-name>A Protected Page</web-resource-name>     <url-pattern>/*</url-pattern>   </web-resource-collection>   <auth-constraint>     <role-name>amqAdminrole-name>   </auth-constraint> </security-constraint>
  <login-config>   <auth-method>BASIC</auth-method>   <realm-name>ActiveMQ Realm</realm-name> </login-config> 
  | 
Make sure, the Realm name matches the one you have set in the Realm definition and the role name match roles you have named in the properties file.
 
5 comments:
Your post is just what i was looking for. Could you post your full activemq.xml? I'm having trouble with xml namespaces and could use further help,
Thanks
!
James,
sorry to react late, but my blog didnt notify me of your message.
I have updated the post with a working version. You were right about the namespaces.
Best regards
Andreas
Thank you very much for this helpful post.
This is great and helpful post. Thank you.
Cybergraphix
Post a Comment