Commit 11e7d9d1 authored by Patrick J Cherry's avatar Patrick J Cherry
Browse files

Added tests to check apache config USING APACHE.

parent 62c72455
......@@ -23,18 +23,29 @@
##
###
NameVirtualHost <%= ip() %>:443
NameVirtualHost <%= ip %>:443
<VirtualHost <%= ip() %>:443>
<VirtualHost <%= ip %>:443>
ServerName <%= domain %>
ServerAlias www.<%= domain %>
SSLEngine On
SSLCertificateFile <%= certificate %>
<% if key_file != certificate_file %>
SSLKeyFile <%= certificate %>
<% end %>
<% if certificate_chain_file %>
SSLCertificateChainFile <%= bundle() %>
<% end %>
#
# The certificate, key, and intermediate bundle (if needed)
#
<%= certificate %>
<%= bundle %>
#
# Sane SSL ciphers.
#
SSLCipherSuite ALL:!LOW:!SSLv2:!EXP:!aNULL
#
# And some options
#
SSLOptions +StrictRequire
......@@ -51,7 +62,7 @@ NameVirtualHost <%= ip() %>:443
#
# Allow users to override settings via .htaccess
#
<Directory "/srv">
<Directory <%=domain_directory%> >
AllowOverride all
</Directory>
......@@ -66,12 +77,12 @@ NameVirtualHost <%= ip() %>:443
#
# The document root
#
DocumentRoot /srv/<%= @domain %>/public/htdocs/
DocumentRoot <%= domain_directory %>/public/htdocs
#
# General CGI Handling
#
ScriptAlias /cgi-bin/ /srv/<%= @domain %>/public/cgi-bin/
ScriptAlias /cgi-bin/ <%= domain_directory %>/public/cgi-bin/
<Location /cgi-bin>
Options +ExecCGI
</Location>
......@@ -83,25 +94,24 @@ NameVirtualHost <%= ip() %>:443
# made against, so that the cron-job in /etc/cron.daily may generate
# statistics for each domain.
#
ErrorLog /var/log/apache2/<%= @domain %>.ssl.error.log
CustomLog /var/log/apache2/<%= @domain %>.ssl.access.log combined
ErrorLog /var/log/apache2/<%= domain %>.ssl.error.log
CustomLog /var/log/apache2/<%= domain %>.ssl.access.log combined
</VirtualHost>
NameVirtualHost <%= ip() %>:80
NameVirtualHost <%= ip %>:80
<VirtualHost <%= ip() %>:80>
<VirtualHost <%= ip %>:80>
<% if mandatory_ssl? %>
#
# All accesses redirect to the HTTPS version of
# the site.
#
Redirect / https://<%= @domain %>/
Redirect / https://<%= domain %>/
<% else %>
#
# This is the directory people are redirected to
# if their site is empty.
......@@ -115,7 +125,7 @@ NameVirtualHost <%= ip() %>:80
#
# Allow users to override settings via .htaccess
#
<Directory "/srv">
<Directory <%=domain_directory%> >
AllowOverride all
</Directory>
......@@ -130,25 +140,23 @@ NameVirtualHost <%= ip() %>:80
#
# The document root
#
DocumentRoot /srv/<%= @domain %>/public/htdocs/
DocumentRoot <%= domain_directory %>/public/htdocs/
#
# General CGI Handling
#
ScriptAlias /cgi-bin/ /srv/<%= @domain %>/public/cgi-bin/
ScriptAlias /cgi-bin/ <%= domain_directory %>/public/cgi-bin/
<Location /cgi-bin>
Options +ExecCGI
</Location>
#
# We need to log the virtual hostname the incoming request was
# made against, so that the cron-job in /etc/cron.daily may generate
# statistics for each domain.
#
ErrorLog /var/log/apache2/<%= @domain %>.error.log
CustomLog /var/log/apache2/<%= @domain %>.access.log combined
ErrorLog /var/log/apache2/<%= domain %>.error.log
CustomLog /var/log/apache2/<%= domain %>.access.log combined
<% end %>
</VirtualHost>
require 'openssl'
require 'erb'
#
# A helper class which copes with SSL-domains.
......@@ -34,11 +35,18 @@ module Symbiosis
File.join(@root_path, "etc", "apache2")
end
#
# Returns the DocumentRoot for the domain.
#
def domain_directory
File.join(@root_path, "srv", @domain)
end
#
# Returns the configuration directory for this domain
#
def config_dir
File.join(@root_path, "srv", @domain, "config")
File.join(self.domain_directory, "config")
end
#
......@@ -61,7 +69,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}.ssl" ) )
File.exists?( File.join( self.apache_dir, "sites-enabled", "#{@domain}.conf" ) )
end
#
......@@ -72,16 +80,25 @@ module Symbiosis
end
#
# Remove the apache file.
# Returns the bundle filename + the apache directive
#
def remove_site
def bundle
return "" unless bundle_file
"SSLCertificateChainFile #{config_dir}/ssl.bundle"
end
if ( File.exists?( "#{self.apache_dir}/sites-enabled/#{@domain}.ssl" ) )
File.unlink( "#{self.apache_dir}/sites-enabled/#{@domain}.ssl" )
end
#
# Returns the certificate (+key) snippet
#
def certificate
return nil unless certificate_file and key_file
if ( File.exists?( "#{self.apache_dir}/sites-available/#{@domain}.ssl" ) )
File.unlink( "#{self.apache_dir}/sites-available/#{@domain}.ssl" )
if certificate_file == key_file
"SSLCertificateFile #{certificate_file}"
else
"SSLCertificateFile #{certificate_file}"
"SSLCertificateKeyFile #{key_file}"
end
end
......@@ -99,7 +116,7 @@ module Symbiosis
#
# Returns the X509 certificate object
#
def certificate
def x509_certificate
if self.certificate_file.nil?
nil
else
......@@ -271,25 +288,25 @@ module Symbiosis
# Firstly check that the certificate is valid for the domain.
#
#
unless OpenSSL::SSL.verify_certificate_identity(self.certificate, @domain) or OpenSSL::SSL.verify_certificate_identity(self.certificate, "www.#{@domain}")
unless OpenSSL::SSL.verify_certificate_identity(self.x509_certificate, @domain) or OpenSSL::SSL.verify_certificate_identity(self.x509_certificate, "www.#{@domain}")
raise OpenSSL::X509::CertificateError, "The certificate subject is not valid for this domain."
end
# Check that the certificate is current
#
#
if self.certificate.not_before > Time.now
if self.x509_certificate.not_before > Time.now
raise OpenSSL::X509::CertificateError, "The certificate is not valid yet."
end
if self.certificate.not_after < Time.now
if self.x509_certificate.not_after < Time.now
raise OpenSSL::X509::CertificateError, "The certificate has expired."
end
# Next check that the key matches the certificate.
#
#
unless self.certificate.check_private_key(self.key)
unless self.x509_certificate.check_private_key(self.key)
raise OpenSSL::X509::CertificateError, "The certificate's public key does not match the supplied private key."
end
......@@ -299,15 +316,15 @@ module Symbiosis
# First see if we can verify it using our own private key, i.e. the
# certificate is self-signed.
#
if self.certificate.verify(self.key)
if self.x509_certificate.verify(self.key)
puts "\tUsing a self-signed certificate." if $VERBOSE
#
# Otherwise see if we can verify it using the certificate store,
# including any bundle that has been uploaded.
#
elsif self.certificate_store.verify(self.certificate)
puts "\tUsing certificate signed by #{self.certificate.issuer.to_s}" if $VERBOSE
elsif self.certificate_store.verify(self.x509_certificate)
puts "\tUsing certificate signed by #{self.x509_certificate.issuer.to_s}" if $VERBOSE
#
# If we can't verify -- raise an error.
......@@ -322,7 +339,7 @@ module Symbiosis
#
# Update Apache to create a site for this domain.
#
def create_ssl_site( tf = File.join(self.root_path, "etc/symbiosis/apache.d/ssl.template.erb") )
def config_snippet( tf = File.join(self.root_path, "etc/symbiosis/apache.d/ssl.template.erb") )
#
# Read the template file.
......@@ -332,22 +349,45 @@ module Symbiosis
#
# Create a template object.
#
template = ERB.new( content )
ERB.new( content ).result( binding )
end
def write_configuration(config = self.config_snippet)
#
# Write out to sites-enabled
#
File.open( File.join( self.apache_dir, "sites-available/#{@domain}.ssl", "w" ) ) do |file|
file.write template.result(binding)
File.open( File.join( self.apache_dir, "sites-available/#{@domain}.conf"), "w+" ) do |file|
file.write config
end
end
#
# Now link in the file
#
File.symlink( File.join( self.apache_dir, "sites-available/#{@domain}.ssl" ),
File.join( self.apache_dir, "sites-enabled/#{@domain}.ssl" ) )
def configuration_ok?
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 }
"Syntax OK" == output.last.chomp
end
def enable_site
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" ) )
end
end
#
# 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
end
#
# Does the SSL site need updating because a file is more
......@@ -358,7 +398,7 @@ module Symbiosis
#
# creation time of the (previously generated) SSL-site.
#
site = File.mtime( "#{self.apache_dir}/sites-available/#{@domain}.ssl" )
site = File.mtime( "#{self.apache_dir}/sites-available/#{@domain}.conf" )
#
......
......@@ -209,7 +209,7 @@ class SSLConfigTest < Test::Unit::TestCase
#
# Return nil if no certificate filename has been set
#
assert_nil(@ssl.certificate)
assert_nil(@ssl.x509_certificate)
#
# Now write the file
......@@ -220,8 +220,8 @@ class SSLConfigTest < Test::Unit::TestCase
#
# Now it should read back the combined file correctly
#
assert_kind_of(crt.class, @ssl.certificate)
assert_equal(crt.to_der, @ssl.certificate.to_der)
assert_kind_of(crt.class, @ssl.x509_certificate)
assert_equal(crt.to_der, @ssl.x509_certificate.to_der)
#
# Generate a new certificate
......@@ -230,14 +230,14 @@ class SSLConfigTest < Test::Unit::TestCase
#
# Make sure it doesn't match the last one
#
assert_not_equal(crt.to_der, @ssl.certificate.to_der)
assert_not_equal(crt.to_der, @ssl.x509_certificate.to_der)
File.open(@domain.directory+"/config/ssl.crt","w+"){|fh| fh.write crt.to_pem}
@ssl.certificate_file = @domain.directory+"/config/ssl.crt"
#
# Now it should read back the individual file correctly
#
assert_equal(crt.to_der, @ssl.certificate.to_der)
assert_equal(crt.to_der, @ssl.x509_certificate.to_der)
end
#
......@@ -523,8 +523,109 @@ class SSLConfigTest < Test::Unit::TestCase
assert_nothing_raised{ @ssl.verify }
end
def test_create_ssl_site
def test_configuration
#
# Set the IP address
#
ip = "1.2.3.4"
File.open(@domain.directory+"/config/ip","w+"){|fh| fh.puts ip}
#
# Generate a key and certificate
#
key, crt = do_generate_key_and_crt(@domain.name, key)
######
#
# Write them into a combined file
#
File.open(@domain.directory+"/config/ssl.combined","w+"){|fh| fh.write crt.to_pem+key.to_pem}
#
# Find a matching key and certificate
#
@ssl.certificate_file, @ssl.key_file = @ssl.find_matching_certificate_and_key
assert_nothing_raised{ @ssl.verify }
#
# Form the configuration snippet
#
if File.exists?("../etc/symbiosis/apache.d/ssl.template.erb")
snippet = @ssl.config_snippet("../etc/symbiosis/apache.d/ssl.template.erb")
else
snippet = @ssl.config_snippet
end
%w(sites-enabled sites-available).each do |d|
FileUtils.mkdir_p(@ssl.apache_dir+"/"+d)
end
assert_nothing_raised{ @ssl.write_configuration(snippet) }
assert(@ssl.configuration_ok?)
####
#
# Now we do separate key+cert
#
File.open(@domain.directory+"/config/ssl.key","w+"){|fh| fh.write key.to_pem}
File.open(@domain.directory+"/config/ssl.crt","w+"){|fh| fh.write crt.to_pem}
#
# Find a matching key and certificate
#
@ssl.certificate_file, @ssl.key_file = @ssl.find_matching_certificate_and_key
assert_nothing_raised{ @ssl.verify }
#
# Form the configuration snippet
#
if File.exists?("../etc/symbiosis/apache.d/ssl.template.erb")
snippet = @ssl.config_snippet("../etc/symbiosis/apache.d/ssl.template.erb")
else
snippet = @ssl.config_snippet
end
%w(sites-enabled sites-available).each do |d|
FileUtils.mkdir_p(@ssl.apache_dir+"/"+d)
end
assert_nothing_raised{ @ssl.write_configuration(snippet) }
assert(@ssl.configuration_ok?)
###
#
# Now we add a bundle
#
ca_cert = OpenSSL::X509::Certificate.new(File.read("RootCA/RootCA.crt"))
ca_key = OpenSSL::PKey::RSA.new(File.read("RootCA/RootCA.key"))
#
# Regenerate our crt
#
crt = do_generate_crt(@domain.name, key, ca_cert, ca_key)
File.open(@domain.directory+"/config/ssl.crt","w+"){|fh| fh.write crt.to_pem}
FileUtils.cp("RootCA/RootCA.crt",@domain.directory+"/config/ssl.bundle")
assert_nothing_raised{ @ssl.verify }
#
# Form the configuration snippet
#
if File.exists?("../etc/symbiosis/apache.d/ssl.template.erb")
snippet = @ssl.config_snippet("../etc/symbiosis/apache.d/ssl.template.erb")
else
snippet = @ssl.config_snippet
end
%w(sites-enabled sites-available).each do |d|
FileUtils.mkdir_p(@ssl.apache_dir+"/"+d)
end
assert_nothing_raised{ @ssl.write_configuration(snippet) }
assert(@ssl.configuration_ok?)
end
def test_outdated?
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment