This consists of a new Puppet::Network::HTTPServer::Rack,
plus configuration details for Passenger.

Signed-off-by: Christian Hofstaedtler <[EMAIL PROTECTED]>
---
 ext/passenger/README                   |   63 ++++++++++++++
 ext/passenger/apache2.conf             |   29 ++++++
 ext/passenger/config.ru                |   40 +++++++++
 lib/puppet/network/http_server/rack.rb |  148 ++++++++++++++++++++++++++++++++
 4 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100644 ext/passenger/README
 create mode 100644 ext/passenger/apache2.conf
 create mode 100644 ext/passenger/config.ru
 create mode 100644 lib/puppet/network/http_server/rack.rb

diff --git a/ext/passenger/README b/ext/passenger/README
new file mode 100644
index 0000000..fcdcb91
--- /dev/null
+++ b/ext/passenger/README
@@ -0,0 +1,63 @@
+
+PUPPETMASTER INSIDE APACHE & PASSENGER
+======================================
+
+This is about running a puppetmaster inside Apache.
+
+Please also see the docs at 
http://reductivelabs.com/trac/puppet/wiki/UsingPassenger
+for further information.
+
+
+WHAT IS IT?
+===========
+
+Passenger [1] (AKA mod_rails or mod_rack) is an Apache 2.x Extension for 
+serving Rails or Rack applications.
+
+This extension allows running a puppetmasterd as a Rack application;
+it has only been tested with Passenger.
+
+
+SHORT INSTALLATION INSTRUCTIONS
+===============================
+
+Make sure puppetmasterd ran at least once, so the SSL certificates
+got set up. 
+
+Install Rack:
+  gem install -v 0.4.0 rack
+
+Install Apache and Passenger:
+  apt-get install apache2
+  gem install passenger
+  passenger-install-apache2-module
+  (See the Passenger installation instructions [2] for details.)
+
+Enable Apache modules:
+  a2enmod ssl
+  a2enmod headers
+
+Configure Apache:
+  cp apache2.conf /etc/apache2/conf.d/puppetmasterd
+  vim /etc/apache2/conf.d/puppetmasterd (replace the server hostnames)
+
+Install the rack application [3]:
+  mkdir -p /usr/share/puppet/rack/puppetmasterd
+  mkdir /usr/share/puppet/rack/puppetmasterd/public 
/usr/share/puppet/rack/puppetmasterd/tmp
+  cp config.ru /usr/share/puppet/rack/puppetmasterd
+  chown puppet /usr/share/puppet/rack/puppetmasterd/config.ru
+
+Go:
+/etc/init.d/apache2 restart
+
+
+
+[1] http://www.modrails.com/
+
+[2] http://www.modrails.com/install.html
+
+[3] Passenger will not let applications run as root or the Apache user, 
+instead an implicit setuid will be done, to the user whom owns 
+config.ru. Therefore, config.ru shall be owned by the puppet user.
+
+
diff --git a/ext/passenger/apache2.conf b/ext/passenger/apache2.conf
new file mode 100644
index 0000000..6a8a974
--- /dev/null
+++ b/ext/passenger/apache2.conf
@@ -0,0 +1,29 @@
+Listen 8140
+<VirtualHost *:8140>
+       SSLEngine on
+       SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
+       SSLCertificateFile      
/var/lib/puppet/ssl/certs/puppet-server.inqnet.at.pem
+       SSLCertificateKeyFile   
/var/lib/puppet/ssl/private_keys/puppet-server.inqnet.at.pem
+       SSLCertificateChainFile /var/lib/puppet/ssl/ca/ca_crt.pem
+       SSLCACertificateFile    /var/lib/puppet/ssl/ca/ca_crt.pem
+       # If Apache complains about invalid signatures on the CRL, you can try 
disabling
+       # CRL checking by commenting the next line.
+       SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
+       SSLVerifyClient optional
+       SSLVerifyDepth  1
+       SSLOptions +StdEnvVars
+
+       # The following client headers allow the same configuration to work 
with Pound.
+       RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
+       RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
+       RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
+
+       RackAutoDetect On
+       DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
+       <Directory /usr/share/puppet/rack/puppetmasterd/>
+               Options None
+               AllowOverride None
+               Order allow,deny
+               allow from all
+       </Directory>
+</VirtualHost>
diff --git a/ext/passenger/config.ru b/ext/passenger/config.ru
new file mode 100644
index 0000000..8608292
--- /dev/null
+++ b/ext/passenger/config.ru
@@ -0,0 +1,40 @@
+# Author: Christian Hofstaedtler <[EMAIL PROTECTED]>
+# Copyright (c) 2007 Luke Kanies, 2008 Christian Hofstaedtler
+#
+# This file is mostly based on puppetmasterd, which is part of
+# the standard puppet distribution.
+
+require 'rack'
+require 'puppet'
+require 'puppet/network/http_server/rack'
+
+# startup code from bin/puppetmasterd
+Puppet.parse_config
+Puppet::Util::Log.level = :info
+Puppet::Util::Log.newdestination(:syslog)
+# A temporary solution, to at least make the master work for now.
+Puppet::Node::Facts.terminus_class = :yaml
+# Cache our nodes in yaml.  Currently not configurable.
+Puppet::Node.cache_class = :yaml
+
+# The list of handlers running inside this puppetmaster
+handlers = {
+       :Status => {},
+       :FileServer => {},
+       :Master => {},
+       :CA => {},
+       :FileBucket => {},
+       :Report => {}
+}
+
+# Fire up the Rack-Server instance
+server = Puppet::Network::HTTPServer::Rack.new(handlers)
+
+# prepare the rack app
+app = proc do |env|
+       server.process(env)
+end
+
+# Go.
+run app
+
diff --git a/lib/puppet/network/http_server/rack.rb 
b/lib/puppet/network/http_server/rack.rb
new file mode 100644
index 0000000..801c9d1
--- /dev/null
+++ b/lib/puppet/network/http_server/rack.rb
@@ -0,0 +1,148 @@
+# Author: Christian Hofstaedtler <[EMAIL PROTECTED]>
+# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies,
+#               2008 Christian Hofstaedtler
+#
+# This file is mostly based on the mongrel module, which is part of
+# the standard puppet distribution.
+#
+# puppet/network/http_server/mongrel.rb has the following license, 
+# and is based heavily on a file retrieved from:
+# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+require 'puppet'
+require 'puppet/network/handler'
+require 'puppet/sslcertificates'
+
+require 'xmlrpc/server'
+require 'puppet/network/xmlrpc/server'
+require 'puppet/network/http_server'
+require 'puppet/network/client_request'
+require 'puppet/network/handler'
+
+require 'resolv'
+require 'rack'
+
+# A handler for a Rack-style puppet(master)d. For the most part, it works 
+# exactly the same as HTTPServer::Mongrel:
+# After checking whether the request itself is sane, the handler forwards 
+# it to an internal instance of XMLRPC::BasicServer to process it.
+module Puppet::Network
+       class HTTPServer::Rack
+               attr_reader :xmlrpc_server
+
+               def initialize(handlers)
+                       @debug = false
+                       if Puppet[:debug]
+                               @debug = true
+                       end
+
+                       Puppet.info "Starting Rack server for puppet version 
%s" % Puppet.version
+                       if Puppet[:name] != "puppetmasterd" then
+                               Puppet.warning 'Rack server is not named 
"puppetmasterd", this may be not what you want. ($0 = %s)' % $0
+                       end
+
+                       @xmlrpc_server = Puppet::Network::XMLRPCServer.new
+                       handlers.each do |name, args|
+                               unless handler = 
Puppet::Network::Handler.handler(name)
+                                       raise ArgumentError, "Invalid handler 
%s" % name
+                               end
+                               h = handler.new(args)
+                               @xmlrpc_server.add_handler(handler.interface, h)
+                       end
+                       Puppet.info "Rack server is waiting to serve requests."
+               end
+
+               # Validate a rack-style request (in env), and run the requested 
XMLRPC
+               # call.
+               def process(env)
+                       # time to serve a request
+                       req = Rack::Request.new(env)
+
+                       if @debug then
+                               Puppet.info "Handling request, details:"
+                               env.each do |name, val|
+                                       l = "  env: %s ->" % name
+                                       l = l + ' %s' % val
+                                       Puppet.info l
+                               end
+                       end
+
+                       if not req.post? then
+                               return [405, { "Content-Type" => "text/html" }, 
"Method Not Allowed"]
+                       end
+                       if req.media_type() != "text/xml" then
+                               return [400, { "Content-Type" => "text/html" }, 
"Bad Request"]
+                       end
+                       if req.content_length().to_i <= 0 then
+                               return [411, { "Content-Type" => "text/html" }, 
"Length Required"]
+                       end
+
+                       body = ''
+                       req.body().each { |line| body = body + line }
+                       if @debug then
+                               Puppet.info "Request Body: %s" % body
+                       end
+                       if body.size != req.content_length().to_i then
+                               if @debug then
+                                       Puppet.info "body length didnt match 
%d" % body.size
+                                       Puppet.info " vs. -> %d" % 
req.content_length().to_i
+                               end
+                               return [400, { "Content-Type" => "text/html" }, 
"Bad Request Length"]
+                       end
+                       info = client_info(env)
+                       begin
+                               data = @xmlrpc_server.process(body, info)
+                               return [200, { "Content-Type" => "text/xml; 
charset=utf-8" }, data]
+                       rescue => detail
+                               Puppet.err "Rack: Internal Server Error: 
XMLRPC_Server.process problem. Details follow: "
+                               detail.backtrace.each { |line|  Puppet.err " 
--> %s" % line }
+                               return [500, { "Content-Type" => "text/html" }, 
"Internal Server Error"]
+                       end
+               end
+
+               private
+
+               def client_info(request)
+                       ip = request["REMOTE_ADDR"]
+                       # JJM #906 The following dn.match regular expression is 
forgiving
+                       # enough to match the two Distinguished Name string 
contents
+                       # coming from Apache, Pound or other reverse SSL 
proxies.
+                       if dn = request[Puppet[:ssl_client_header]] and 
dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
+                               client = dn_matchdata[1].to_str
+                               valid = 
(request[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
+                       else
+                               begin
+                                       client = Resolv.getname(ip)
+                               rescue => detail
+                                       Puppet.err "Could not resolve %s: %s" % 
[ip, detail]
+                                       client = "unknown"
+                               end
+                               valid = false
+                       end
+                       info = Puppet::Network::ClientRequest.new(client, ip, 
valid)
+                       return info
+               end
+       end
+end
+
-- 
1.5.4.3


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to