Commit 99701c4a authored by Patrick J Cherry's avatar Patrick J Cherry
Browse files

Cronjobs for apache are now symlinked from /usr/sbin

Moved source around for apache
Changed shells for autobuild scripts to bash.
parent 11e7d9d1
#!/usr/bin/ruby
#
# NAME
#
# create-ssl-sites -- Auto-configure SSL sites
#
# SYNOPSIS
#
# General Options:
#
# --force Force the re-creation of all SSL sites.
# --template Specify an alternative template file to read.
#
# Help Options:
#
# --help Show the help information for this script.
# --verbose Show debugging information.
#
# DETAILS
#
# This script is designed to iterate over the domains hosted
# upon a Symbiosis system, and configure Apache to listen appropriate
# when a domain is configured for SSL hosting and not yet configured.
#
# AUTHOR
#
# Steve Kemp <steve@bytemark.co.uk>
#
require 'erb'
require 'getoptlong'
require 'symbiosis/domains.rb'
#
# A helper class which copes with SSL-domains.
#
#
class SSLConfiguration
#
# The domain this object is working with.
#
attr_reader :domain
#
# Constructor.
#
def initialize( domain )
@domain = domain
end
#
# Is SSL enabled for the domain?
#
# SSL is enabled if we have:
#
# /srv/$domain/config/ip
#
# And one of:
#
# /srv/$domain/config/ssl.key
# /srv/$doamin/config/ssl.combined
#
def ssl_enabled?
#
# SSL is never enabled unless we have /config/ip
#
if ( ! File.exists?( "/srv/#{@domain}/config/ip" ) )
return false
end
if ( File.exists?( "/srv/#{@domain}/config/ssl.key" ) ||
File.exists?( "/srv/#{@domain}/config/ssl.combined" ) )
true
else
false
end
end
#
# Is there an Apache site enabled for this domain?
#
def site_enabled?
File.exists?( "/etc/apache2/sites-enabled/#{@domain}.ssl" )
end
#
# Do we redirect to the SSL only version of this site?
#
def mandatory_ssl?
if ( File.exists?( "/srv/#{@domain}/config/ssl-only" ) )
true
else
false
end
end
#
# Remove the apache file.
#
def remove_site
if ( File.exists?( "/etc/apache2/sites-enabled/#{@domain}.ssl" ) )
File.unlink( "/etc/apache2/sites-enabled/#{@domain}.ssl" )
end
if ( File.exists?( "/etc/apache2/sites-available/#{@domain}.ssl" ) )
File.unlink( "/etc/apache2/sites-available/#{@domain}.ssl" )
end
end
#
# Get the IP for this domain.
#
def ip
File.open("/srv/#{@domain}/config/ip"){|fh| fh.readlines}.first.chomp
end
#
# Return the bundle configuration to use, if any.
#
def bundle
if ( File.exists?( "/srv/#{@domain}/config/ssl.bundle" ) )
"SSLCertificateChainFile /srv/#{@domain}/config/ssl.bundle"
else
""
end
end
#
# Return the certificate file
#
def certificate
if ( File.exists?( "/srv/#{@domain}/config/ssl.combined" ) )
return "SSLCertificateFile /srv/#{@domain}/config/ssl.combined"
end
#
# OK we might have the combined values in "ssl.key", or we might
# have "ssl.key" + "ssl.cert"
#
# If both the latter exist we'll treat them separately.
#
if ( File.exists?( "/srv/#{@domain}/config/ssl.key" ) &&
File.exists?( "/srv/#{@domain}/config/ssl.cert" ) )
return "SSLCertificateFile /srv/#{@domain}/config/ssl.key\nSSLCertificateKeyFile /srv/#{@domain}/config/ssl.cert"
end
#
# We hope like hell we have ssl.key which is a combined one.
#
if ( File.exists?( "/srv/#{@domain}/config/ssl.key" ) )
return "SSLCertificateFile /srv/#{@domain}/config/ssl.key"
end
""
end
#
# Update Apache to create a site for this domain.
#
def create_ssl_site( tf = nil )
#
# If we have no template file use the default.
#
tf = "/etc/symbiosis/apache.d/ssl.template.erb" if ( tf.nil?)
#
# Read the template file.
#
content = File.open( tf, "r" ).read()
#
# Create a template object.
#
template = ERB.new( content )
#
# Write out to sites-enabled
#
File.open( "/etc/apache2/sites-available/#{@domain}.ssl", "w" ) do |file|
file.write template.result(binding)
end
#
# Now link in the file
#
File.symlink( "/etc/apache2/sites-available/#{@domain}.ssl",
"/etc/apache2/sites-enabled/#{@domain}.ssl" )
end
#
# Does the SSL site need updating because a file is more
# recent than the generated Apache site?
#
def outdated?
#
# creation time of the (previously generated) SSL-site.
#
site = File.mtime( "/etc/apache2/sites-available/#{@domain}.ssl" )
#
# For each configuration file see if it is more recent
#
files = %w( ssl.combined ssl.key ssl.bundle ip )
files.each do |file|
if ( File.exists?( "/srv/#{@domain}/config/#{file}" ) )
mtime = File.mtime("/srv/#{@domain}/config/#{file}" )
if ( mtime > site )
return true
end
end
end
false
end
end
#
# Entry point to the code
#
if __FILE__ == $0 then
$FORCE = false
$HELP = false
$TEMPLATE = nil
$VERBOSE = false
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
[ '--template', '-t', GetoptLong::REQUIRED_ARGUMENT ],
[ '--force', '-f', GetoptLong::NO_ARGUMENT ]
)
opts.each do |opt, arg|
case opt
when '--help'
$HELP = true
when '--verbose'
$VERBOSE = true
when '--template'
$TEMPLATE = arg
when '--force'
$FORCE = true
end
end
#
# CAUTION! Here be quality kode.
#
if $HELP
# Open the file, stripping the shebang line
lines = File.open(__FILE__){|fh| fh.readlines}[2..-1]
lines.each do |line|
line.chomp!
break if line.empty?
puts line[2..-1].to_s
end
exit 0
end
#
# Do we need to restart apache?
#
$RESTART=false
#
# For each domain.
#
helper = Symbiosis::Domains.new()
helper.domains.each do |domain|
puts "Domain: #{domain} " if ( $VERBOSE )
#
# Create a helper for the domain.
#
helper = SSLConfiguration.new( domain )
#
# If SSL is not enabled then we can skip
#
if ( helper.ssl_enabled? )
puts "\tSSL is enabled" if ( $VERBOSE )
#
# If there is already a site enabled we only
# need to touch it if one of the SSL-files is more
# recent than the generated file.
#
# e.g. User adds /config/ssl.combined and a site
# is generated but broken because a mandatory bundle is missing.
#
if ( helper.site_enabled? )
puts "\tSite already present" if ( $VERBOSE )
if ( $FORCE || ( helper.outdated? ) )
if ( $FORCE )
puts "\tForcing re-creation due to --force" if ( $VERBOSE )
else
puts "\tRecreating as it is older than the input file(s)" if ( $VERBOSE )
end
helper.remove_site()
helper.create_ssl_site( $TEMPLATE )
$RESTART = true
else
puts "\tLeaving as-is" if ( $VERBOSE )
end
else
puts "\tSite not already present" if ( $VERBOSE )
#
# Create site.
#
helper.create_ssl_site( $TEMPLATE )
$RESTART=true
end
else
puts "\tSSL is not enabled" if ( $VERBOSE )
end
end
#
# All done.
#
if ( $RESTART )
puts "Restarting Apache" if ( $VERBOSE )
system( "/etc/init.d/apache2 restart" )
end
end
bin/create-ssl-sites etc/cron.hourly/
bin/configure-additional etc/cron.hourly/
bin/make-logs etc/cron.daily/
bin/symbiosis-combine-ssl usr/bin
etc/* etc/
\ No newline at end of file
sbin usr/
test.d etc/symbiosis/
apache.d etc/symbiosis/
lib/* usr/lib/ruby/1.8/
......@@ -269,6 +269,12 @@ else
makessl=1
fi
#
# Rename ssl.pem to ssl.crt.
#
if [ -e /etc/ssl/ssl.pem ] ; then
mv /etc/ssl/ssl.pem /etc/ssl/ssl.crt
fi
if [ "$makessl" == "1" ]; then
......@@ -277,12 +283,12 @@ if [ "$makessl" == "1" ]; then
#
# Make the key
#
openssl req -subj "/C=GB/ST=England/L=York/CN=$(cat /etc/hostname)" -new -x509 -days 3650 -nodes -out /etc/ssl/ssl.pem -keyout /etc/ssl/ssl.key
openssl req -subj "/C=GB/ST=England/L=York/CN=$(cat /etc/hostname)" -new -x509 -days 3650 -nodes -out /etc/ssl/ssl.crt -keyout /etc/ssl/ssl.key
#
# Combine PEM + Key
# Combine Cert + Key
#
cat /etc/ssl/ssl.key /etc/ssl/ssl.pem > /etc/ssl/ssl.combined
cat /etc/ssl/ssl.key /etc/ssl/ssl.crt > /etc/ssl/ssl.combined
fi
......@@ -292,8 +298,6 @@ fi
a2ensite zz-mass-hosting >/dev/null 2>/dev/null
a2ensite zz-mass-hosting.ssl >/dev/null 2>/dev/null
#
# Enable common modules
#
......@@ -366,14 +370,27 @@ if [ -e /etc/php5/apache2/php.ini ]; then
fi
fi
#
# If we have additional sites add them
#
if [ -x /etc/cron.hourly/configure-additional ]; then
/etc/cron.hourly/configure-additional
if [ -x /usr/sbin/symbiosis-configure-additional ]; then
/usr/sbin/symbiosis-configure-additional
#
# And install the cron job
#
ln -s /usr/sbin/symbiosis-configure-additional /etc/cron.hourly
fi
#
# Install cron jobs
#
if [ -x /usr/sbin/symbiosis-configure-ssl ] ; then
ln -s /usr/sbin/symbiosis-configure-ssl /etc/cron.hourly
fi
if [ -x /usr/sbin/symbiosis-make-logs ] ; then
ln -s /usr/sbin/symbiosis-make-logs /etc/cron.daily
fi
#
# Restart Apache2.
......
......@@ -35,6 +35,17 @@ module Symbiosis
File.join(@root_path, "etc", "apache2")
end
#
# Returns the site-enabled filename
#
def sites_enabled_file
File.join(self.apache_dir,"sites-enabled","#{@domain}.conf")
end
def sites_available_file
File.join(self.apache_dir,"sites-available","#{@domain}.conf")
end
#
# Returns the DocumentRoot for the domain.
#
......@@ -69,7 +80,7 @@ module Symbiosis
# Is there an Apache site enabled for this domain?
#
def site_enabled?
File.exists?( File.join( self.apache_dir, "sites-enabled", "#{@domain}.conf" ) )
File.exists?( self.sites_enabled_file )
end
#
......@@ -97,8 +108,7 @@ module Symbiosis
if certificate_file == key_file
"SSLCertificateFile #{certificate_file}"
else
"SSLCertificateFile #{certificate_file}"
"SSLCertificateKeyFile #{key_file}"
"SSLCertificateFile #{certificate_file}\nSSLCertificateKeyFile #{key_file}"
end
end
......@@ -142,7 +152,12 @@ module Symbiosis
if @certificate_chain_file.nil? and File.exists?( File.join( self.config_dir,"ssl.bundle" ) )
@certificate_chain_file = File.join( self.config_dir,"ssl.bundle" )
end
@certificate_chain_file
if @certificate_chain_file and File.exists?(@certificate_chain_file)
@certificate_chain_file
else
nil
end
end
alias bundle_file certificate_chain_file
......@@ -356,8 +371,9 @@ module Symbiosis
#
# Write out to sites-enabled
#
File.open( File.join( self.apache_dir, "sites-available/#{@domain}.conf"), "w+" ) do |file|
File.open( self.sites_available_file, "w+" ) do |file|
file.write config
file.puts "# Checksum MD5 "+OpenSSL::Digest::MD5.new(config).hexdigest
end
end
......@@ -365,7 +381,9 @@ module Symbiosis
return false unless File.executable?("/usr/sbin/apache2")
output = []
IO.popen( "/usr/sbin/apache2 -C 'Include /etc/apache2/mods-enabled/*.load' -C 'Include /etc/apache2/mods-enabled/*.conf' -f #{File.join( self.apache_dir, "sites-available/#{@domain}.conf")} -t 2>&1 ") {|io| output = io.readlines }
IO.popen( "/usr/sbin/apache2 -C 'UseCanonicalName off' -C 'Include /etc/apache2/mods-enabled/*.load' -C 'Include /etc/apache2/mods-enabled/*.conf' -f #{self.sites_available_file} -t 2>&1 ") {|io| output = io.readlines }
warn output.collect{|o| "\t"+o}.join unless "Syntax OK" == output.last.chomp or $VERBOSE
"Syntax OK" == output.last.chomp
end
......@@ -374,8 +392,7 @@ module Symbiosis
if configuration_ok?
# Now link in the file
#
File.symlink( File.join( self.apache_dir, "sites-available/#{@domain}.conf" ),
File.join( self.apache_dir, "sites-enabled/#{@domain}.conf" ) )
File.symlink( self.sites_available_file, self.sites_enabled_file )
end
end
......@@ -383,12 +400,9 @@ module Symbiosis
# Remove the apache file.
#
def disable_site
if ( File.exists?( "#{self.apache_dir}/sites-enabled/#{@domain}.conf" ) )
File.unlink( "#{self.apache_dir}/sites-enabled/#{@domain}.conf" )
end
File.unlink( self.sites_enabled_file ) if File.exists?( self.sites_enabled_file )
end
#
# Does the SSL site need updating because a file is more
# recent than the generated Apache site?
......@@ -398,25 +412,67 @@ module Symbiosis
#
# creation time of the (previously generated) SSL-site.
#
site = File.mtime( "#{self.apache_dir}/sites-available/#{@domain}.conf" )
site = File.mtime( self.sites_available_file )
#
# For each configuration file see if it is more recent
#
files = %w( ssl.combined ssl.key ssl.bundle ip )
files.each do |file|
if ( File.exists?( File.join( self.config_dir, file ) ) )
mtime = File.mtime( File.join( self.config_dir, file ) )
if ( mtime > site )
return true
end
end
%w( ssl.combined ssl.key ssl.bundle ip ).each do |file|
file = File.join( self.config_dir, file )
return true if File.exists?( file ) and File.mtime( file ) > site
end
false
end
#
# This opens the config sni
#
def changed?
#
# Read the snippet
#
snippet = File.readlines(self.sites_available_file)
#
# We expect the checksum to be the last line of the file
#
if snippet.last.chomp =~ /^# Checksum MD5 ([a-f0-9]{32,32})$/
#
# OK we've found the checksum
#
supposed_checksum = $1
#
# Pop off the last line, as this isn't part of the checksum
#
snippet.pop
#
# And compare to the calculated checksum of the rest of the snippet
#
return OpenSSL::Digest::MD5.new(snippet.join).hexdigest != supposed_checksum
#
# We're OK if the file has a big warning in it.
#
elsif snippet.any?{|l| "# DO NOT EDIT THIS FILE - CHANGES WILL BE OVERWRITTEN" == l.chomp}
#
# So return true
#
return false