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 2011/05/18 23:21:16 UTC

svn commit: r1124435 - 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/jetty/ apollo-broker/src/main/scala/org/apache/activemq/apollo/bro...

Author: chirino
Date: Wed May 18 21:21:16 2011
New Revision: 1124435

URL: http://svn.apache.org/viewvc?rev=1124435&view=rev
Log:
Fixes https://issues.apache.org/jira/browse/APLO-11 : Added support for binding the web admin interface to https.

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/jetty/JettyWebServer.scala
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/web/WebServerFactory.scala
    activemq/activemq-apollo/trunk/apollo-cli/src/main/resources/org/apache/activemq/apollo/cli/commands/etc/apollo-ssl.xml
    activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Stop.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/ApolloThreadPool.java
    activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/osgi/OsgiWebServerFactory.scala
    activemq/activemq-apollo/trunk/apollo-website/src/documentation/getting-started.md
    activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md
    activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md

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=1124435&r1=1124434&r2=1124435&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 Wed May 18 21:21:16 2011
@@ -170,8 +170,8 @@ object Broker extends Log {
       for (connector <- config.connectors ) {
         result |= Connector.validate(connector, reporter)
       }
-      if( config.web_admin != null ) {
-        WebServerFactory.validate(config.web_admin, reporter)
+      if( !config.web_admins.isEmpty ) {
+        WebServerFactory.validate(config.web_admins.toList, reporter)
       }
 
     }.result
@@ -310,7 +310,7 @@ class Broker() extends BaseService {
     val first_tracker = new LoggingTracker("broker startup", console_log, dispatch_queue)
     val second_tracker = new LoggingTracker("broker startup", console_log, dispatch_queue)
 
-    Option(config.web_admin).foreach{ web_admin=>
+    if( !config.web_admins.isEmpty ) {
       WebServerFactory.create(this) match {
         case null =>
           warn("Could not start admistration interface.")

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/jetty/JettyWebServer.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/jetty/JettyWebServer.scala?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/jetty/JettyWebServer.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/jetty/JettyWebServer.scala Wed May 18 21:21:16 2011
@@ -30,6 +30,13 @@ import java.io.File
 import java.lang.String
 import org.apache.activemq.apollo.broker.web.{WebServer, WebServerFactory}
 import java.net.URI
+import org.eclipse.jetty.server.handler.HandlerList
+import collection.mutable.{HashMap, ListBuffer}
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector
+import javax.net.ssl.KeyManager
+import javax.net.ssl.SSLContext
+import javax.net.ssl.TrustManager
+import org.eclipse.jetty.util.thread.ExecutorThreadPool
 
 /**
  * <p>
@@ -55,7 +62,7 @@ object JettyWebServerFactory extends Web
     new JettyWebServer(broker)
   }
 
-  def validate(config: WebAdminDTO, reporter: Reporter): ReporterLevel.ReporterLevel = {
+  def validate(config: List[WebAdminDTO], reporter: Reporter): ReporterLevel.ReporterLevel = {
     if( !enabled ) {
       return null
     }
@@ -147,13 +154,6 @@ class JettyWebServer(val broker:Broker) 
       import collection.JavaConversions._
 
       val config = broker.config
-      val web_admin = config.web_admin
-
-      val bind = web_admin.bind.getOrElse("http://127.0.0.1:61680")
-      val bind_uri = new URI(bind)
-      val prefix = "/"+bind_uri.getPath.stripPrefix("/")
-      val host = bind_uri.getHost
-      val port = bind_uri.getPort
 
       // Start up the admin interface...
       debug("Starting administration interface");
@@ -162,21 +162,72 @@ class JettyWebServer(val broker:Broker) 
         System.setProperty("scalate.workdir", (broker.tmp / "scalate").getCanonicalPath )
       }
 
-      var connector = new SelectChannelConnector
-      connector.setHost(host)
-      connector.setPort(port)
+      val contexts = HashMap[String, Handler]()
+      val connectors = HashMap[String, Connector]()
+
+      config.web_admins.foreach { web_admin =>
+
+        val bind = web_admin.bind.getOrElse("http://127.0.0.1:61680")
+        val bind_uri = new URI(bind)
+        val prefix = "/"+bind_uri.getPath.stripPrefix("/")
+
+        val scheme = bind_uri.getScheme
+        val host = bind_uri.getHost
+        var port = bind_uri.getPort
+
+        scheme match {
+          case "http" =>
+            if (port == -1) {
+              port = 80
+            }
+          case "https" =>
+            if (port == -1) {
+              port = 443
+            }
+          case _ => throw new Exception("Invalid 'web_admin' bind setting.  The protocol scheme must be http or https.")
+        }
+
+        // Only add the connector if not yet added..
+        val connector_id = scheme+"://"+bind_uri+":"+port
+        if ( !connectors.containsKey(connector_id) ) {
+
+          val connector = scheme match {
+            case "http" => new SelectChannelConnector
+            case "https" =>
+              val sslContext = if( broker.key_storage!=null ) {
+                val protocol = "TLS"
+                val sslContext = SSLContext.getInstance (protocol)
+                sslContext.init(broker.key_storage.create_key_managers, broker.key_storage.create_trust_managers, null)
+                sslContext
+              } else {
+                SSLContext.getDefault
+              }
+
+              val connector = new SslSelectChannelConnector
+              connector.setSslContext(sslContext)
+              connector
+          }
+
 
+          connector.setThreadPool(new ExecutorThreadPool(Broker.BLOCKABLE_THREAD_POOL))
+          connector.setHost(host)
+          connector.setPort(port)
+          connectors.put(connector_id, connector)
+        }
 
-      def admin_app = {
-        var app_context = new WebAppContext
-        app_context.setContextPath(prefix)
-        app_context.setWar(webapp.getCanonicalPath)
-        if( broker.tmp !=null ) {
-          app_context.setTempDirectory(broker.tmp)
+        // Only add the app context if not yet added..
+        if ( !contexts.containsKey(prefix) ) {
+          var context = new WebAppContext
+          context.setContextPath(prefix)
+          context.setWar(webapp.getCanonicalPath)
+          if( broker.tmp !=null ) {
+            context.setTempDirectory(broker.tmp)
+          }
+          contexts.put(prefix, context)
         }
-        app_context
       }
 
+
       def secured(handler:Handler) = {
         if( config.authentication!=null && config.acl!=null ) {
           val security_handler = new ConstraintSecurityHandler
@@ -206,14 +257,24 @@ class JettyWebServer(val broker:Broker) 
         }
       }
 
+      val context_list = new HandlerList
+      contexts.values.foreach(context_list.addHandler(_))
+
       server = new Server
-      server.setHandler(secured(admin_app))
-      server.setConnectors(Array[Connector](connector))
+      server.setHandler(secured(context_list))
+      server.setConnectors(connectors.values.toArray)
       server.start
 
-      val localPort = connector.getLocalPort
-      def url = new URI("http", null, host, localPort, prefix, null, null).toString
-      broker.console_log.info("Administration interface available at: "+url)
+      for( connector <- connectors.values ; prefix <- contexts.keys ) {
+        val localPort = connector.getLocalPort
+        val scheme = connector match {
+          case x:SslSelectChannelConnector => "https"
+          case _ => "http"
+        }
+
+        def url = new URI(scheme, null, connector.getHost, localPort, prefix, null, null).toString
+        broker.console_log.info("Administration interface available at: "+url)
+      }
       on_completed.run
     }
   }

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/web/WebServerFactory.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/web/WebServerFactory.scala?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/web/WebServerFactory.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/web/WebServerFactory.scala Wed May 18 21:21:16 2011
@@ -39,7 +39,7 @@ object WebServerFactory {
 
   trait Provider {
     def create(broker:Broker):WebServer
-    def validate(config: WebAdminDTO, reporter:Reporter):ReporterLevel
+    def validate(config: List[WebAdminDTO], reporter:Reporter):ReporterLevel
   }
 
   val providers = new ClassFinder[Provider]("META-INF/services/org.apache.activemq.apollo/web-server-factory.index",classOf[Provider])
@@ -58,7 +58,7 @@ object WebServerFactory {
   }
 
 
-  def validate(config: WebAdminDTO, reporter:Reporter):ReporterLevel = {
+  def validate(config: List[WebAdminDTO], reporter:Reporter):ReporterLevel = {
     if( config == null ) {
       return INFO
     } else {

Modified: activemq/activemq-apollo/trunk/apollo-cli/src/main/resources/org/apache/activemq/apollo/cli/commands/etc/apollo-ssl.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-cli/src/main/resources/org/apache/activemq/apollo/cli/commands/etc/apollo-ssl.xml?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-cli/src/main/resources/org/apache/activemq/apollo/cli/commands/etc/apollo-ssl.xml (original)
+++ activemq/activemq-apollo/trunk/apollo-cli/src/main/resources/org/apache/activemq/apollo/cli/commands/etc/apollo-ssl.xml Wed May 18 21:21:16 2011
@@ -56,6 +56,7 @@
   </virtual_host>
 
   <web_admin bind="http://127.0.0.1:61680"/>
+  <web_admin bind="https://127.0.0.1:61681"/>
 
   <connector id="tcp" bind="tcp://0.0.0.0:61613" connection_limit="2000"/>
   <connector id="tls" bind="tls://0.0.0.0:61614" connection_limit="2000"/>

Modified: activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Stop.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Stop.scala?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Stop.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-cli/src/main/scala/org/apache/activemq/apollo/cli/commands/Stop.scala Wed May 18 21:21:16 2011
@@ -57,31 +57,29 @@ class Stop extends Action with Logging {
 
       val config = new FileConfigStore(conf).load(true)
 
-      Option(config.web_admin) match {
-        case None=>
-          error("Web admin not enabled for that configuration, sorry can't shut the broker down");
-
-        case Some(web_admin)=>
-        
-          val bind = web_admin.bind.getOrElse("http://localhost:61680")
-          val bind_uri = new URI(bind)
-          val prefix = bind_uri.getPath.stripSuffix("/")
-          val host = "localhost"
-          val port = bind_uri.getPort
-
-          val auth = (user, password) match {
-            case (null,null)=> None
-            case (null,p)=> Some(":"+p)
-            case (u,null)=> Some(u+":")
-            case (u,p)=> Some(u+":"+p)
-          }
-
-          val connection = new URL(
-            "http://%s:%s%s/runtime/action/shutdown".format(host, port, prefix)
-          ).openConnection.asInstanceOf[HttpURLConnection]
-          connection.setRequestMethod("POST");
-          auth.foreach{x=> connection.setRequestProperty("Authorization", "Basic "+new String(Base64.encodeBase64(x.getBytes("UTF-8")), "UTF-8")) }
-          connection.getContent
+      if(config.web_admins.isEmpty) {
+        error("Web admin not enabled for that configuration, sorry can't shut the broker down");
+      } else {
+
+        val bind = config.web_admins.get(0).bind.getOrElse("http://localhost:61680")
+        val bind_uri = new URI(bind)
+        val prefix = bind_uri.getPath.stripSuffix("/")
+        val host = "localhost"
+        val port = bind_uri.getPort
+
+        val auth = (user, password) match {
+          case (null,null)=> None
+          case (null,p)=> Some(":"+p)
+          case (u,null)=> Some(u+":")
+          case (u,p)=> Some(u+":"+p)
+        }
+
+        val connection = new URL(
+          "http://%s:%s%s/action/shutdown".format(host, port, prefix)
+        ).openConnection.asInstanceOf[HttpURLConnection]
+        connection.setRequestMethod("POST");
+        auth.foreach{x=> connection.setRequestProperty("Authorization", "Basic "+new String(Base64.encodeBase64(x.getBytes("UTF-8")), "UTF-8")) }
+        connection.getContent
       }
 
     } catch {

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=1124435&r1=1124434&r2=1124435&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 Wed May 18 21:21:16 2011
@@ -65,7 +65,7 @@ public class BrokerDTO {
     public BrokerAclDTO acl;
 
     @XmlElement(name="web_admin")
-    public WebAdminDTO web_admin;
+    public List<WebAdminDTO> web_admins = new ArrayList<WebAdminDTO>();
 
     @XmlElement(name="authentication")
     public AuthenticationDTO authentication;

Modified: activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ApolloThreadPool.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ApolloThreadPool.java?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ApolloThreadPool.java (original)
+++ activemq/activemq-apollo/trunk/apollo-util/src/main/scala/org/apache/activemq/apollo/util/ApolloThreadPool.java Wed May 18 21:21:16 2011
@@ -16,6 +16,8 @@
  */
 package org.apache.activemq.apollo.util;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.*;
 
 /**
@@ -30,13 +32,25 @@ public class ApolloThreadPool {
 
     public static final int POOL_SIZE = Integer.parseInt(System.getProperty("apollo.thread.pool", "128"));
 
-    public static final ThreadPoolExecutor INSTANCE = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
+    public static final ThreadPoolExecutor INSTANCE = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
         public Thread newThread(Runnable r) {
             Thread rc = new Thread(r, "Apollo Blocking Task");
             rc.setDaemon(true);
             return rc;
         }
-    });
+    }) {
+
+        @Override
+        public void shutdown() {
+            // we don't ever shutdown since we are shared..
+        }
+
+        @Override
+        public List<Runnable> shutdownNow() {
+            // we don't ever shutdown since we are shared..
+            return Collections.emptyList();
+        }
+    };
 
     static {
         INSTANCE.allowCoreThreadTimeOut(true);

Modified: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/osgi/OsgiWebServerFactory.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/osgi/OsgiWebServerFactory.scala?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/osgi/OsgiWebServerFactory.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/osgi/OsgiWebServerFactory.scala Wed May 18 21:21:16 2011
@@ -54,7 +54,7 @@ class OsgiWebServerFactory  extends WebS
 
   }
 
-  def validate(config: WebAdminDTO, reporter: Reporter): ReporterLevel.ReporterLevel = {
+  def validate(config: List[WebAdminDTO], reporter: Reporter): ReporterLevel.ReporterLevel = {
     if( broker_service.context == null ) {
       return null
     }

Modified: activemq/activemq-apollo/trunk/apollo-website/src/documentation/getting-started.md
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-website/src/documentation/getting-started.md?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-website/src/documentation/getting-started.md (original)
+++ activemq/activemq-apollo/trunk/apollo-website/src/documentation/getting-started.md Wed May 18 21:21:16 2011
@@ -82,7 +82,7 @@ examples to [verify](verification.html) 
 Apollo provides a simple web interface to monitor the status of the broker.  Once
 the admin interface will be accessible at:
 
-* [http://127.0.0.1:61680/](http://127.0.0.1:61680/)
+* [http://127.0.0.1:61680/](http://127.0.0.1:61680/) or [https://127.0.0.1:61681/](https://127.0.0.1:61681/)
 
 The default login id and password is `admin` and `password`.
 

Modified: activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md (original)
+++ activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md Wed May 18 21:21:16 2011
@@ -4,11 +4,12 @@
 
 ## Overview
 
-Apollo's REST API runs on port 61680 by default.   If your running 
-an Apollo broker on your local machine, you  would access the 
-API at the following HTTP URL:
+Apollo's REST API runs on port 61680 or via SSL on port 61681. If your
+running an Apollo broker on your local machine, you could access the
+API at the following HTTP URLs:
 
     http://localhost:61680
+    https://localhost:61681
 
 For all of the rest of this document, we will be leaving off that part,
 since it is the same for every API call.
@@ -429,9 +430,9 @@ Results in a [Broker Configuration](./ap
       "kind":null
     }]
   },
-  "web_admin":{
+  "web_admins":[{
     "bind":"http://127.0.0.1:61680"
-  },
+  }],
   "authentication":{
     "enabled":null,
     "domain":"apollo",

Modified: activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md?rev=1124435&r1=1124434&r2=1124435&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md (original)
+++ activemq/activemq-apollo/trunk/apollo-website/src/documentation/user-manual.md Wed May 18 21:21:16 2011
@@ -728,8 +728,9 @@ to the proper value before starting the 
 
 ### Web Based Administration
 
-${project_name} start a web based administration interface on 
-[`http://127.0.0.1:61680`](http://127.0.0.1:61680) by default.  Note
+${project_name} starts a web based administration interface on 
+[`http://127.0.0.1:61680`](http://127.0.0.1:61680) and 
+[`https://127.0.0.1:61681`](https://127.0.0.1:61681) by default.  Note
 that it binds to the loopback interface so that only local web 
 browsers can access the interface.
 
@@ -739,14 +740,17 @@ perform basic authentication and will on
 which are in the admin ACL.
 
 If you want to disable the web the interface then you should remove
-the `web_admin` configuration element. 
+the `web_admin` configuration elements.  If you want to allow 
+remote administration, you should update the configuration so
+it bind either the `0.0.0.0` or `[::]` address.  
 
 For example:
 
 {pygmentize:: xml}
 <broker xmlns="http://activemq.apache.org/schema/activemq/apollo">
   ...
-  <web_admin bind="http://127.0.0.1:61680"/>
+  <web_admin bind="http://0.0.0.0:61680"/>
+  <web_admin bind="https://0.0.0.0:61681"/>
   ...
 </broker>
 {pygmentize}