Skip to content
Snippets Groups Projects
Commit 325cda9a authored by Adrian Rossouw's avatar Adrian Rossouw
Browse files

Added key generation code and abstracted the configuration classes a bit more....

Added key generation code and abstracted the configuration classes a bit more. There are now base http classes that handle the synching to remote servers.
parent 6ef19c36
No related branches found
No related tags found
No related merge requests found
...@@ -19,6 +19,12 @@ class provisionService_http_apache extends provisionService_http_public { ...@@ -19,6 +19,12 @@ class provisionService_http_apache extends provisionService_http_public {
$this->configs['site'][] = 'provisionConfig_apache_site'; $this->configs['site'][] = 'provisionConfig_apache_site';
} }
/**
* Guess at the likely value of the http_restart_cmd.
*
* This method is a static so that it can be re-used by the apache_ssl
* service, even though it does not inherit this class.
*/
public static function apache_restart_cmd() { public static function apache_restart_cmd() {
$command = '/usr/sbin/apachectl'; // A proper default for most of the world $command = '/usr/sbin/apachectl'; // A proper default for most of the world
foreach (explode(':', $_SERVER['PATH']) as $path) { foreach (explode(':', $_SERVER['PATH']) as $path) {
...@@ -49,42 +55,12 @@ class provisionService_http_apache extends provisionService_http_public { ...@@ -49,42 +55,12 @@ class provisionService_http_apache extends provisionService_http_public {
} }
} }
class provisionConfig_apache extends provisionConfig {
function write() {
parent::write();
$this->data['server']->sync($this->filename());
}
function unlink() {
parent::unlink();
$this->data['server']->sync($this->filename());
}
}
/** /**
* Apache server level configuration file class * Apache server level configuration file class
*/ */
class provisionConfig_apache_server extends provisionConfig_apache { class provisionConfig_apache_server extends provisionConfig_http_server {
public $template = 'server.tpl.php';
public $description = 'apache server configuration file';
function write() {
parent::write();
// We link the apache.config file on the remote server to the right version.
$cmd = sprintf('ln -sf %s %s',
escapeshellarg($this->data['server']->config_path . '/apache.conf'),
escapeshellarg($this->data['server']->aegir_root . '/config/apache.conf')
);
$this->data['server']->shell_exec($cmd);
}
function filename() {
return $this->data['server']->config_path . '/apache.conf';
}
function process() { function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n"; $this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data)); $this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data));
} }
...@@ -93,15 +69,9 @@ class provisionConfig_apache_server extends provisionConfig_apache { ...@@ -93,15 +69,9 @@ class provisionConfig_apache_server extends provisionConfig_apache {
/** /**
* Apache platform level configuration file class * Apache platform level configuration file class
*/ */
class provisionConfig_apache_platform extends provisionConfig_apache { class provisionConfig_apache_platform extends provisionConfig_http_platform {
public $template = 'platform.tpl.php';
public $description = 'apache platform configuration file';
function filename() {
return $this->data['http_platformd_path'] . '/' . ltrim($this->owner->name, '@') . '.conf';
}
function process() { function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n"; $this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_dir_config', $this->data)); $this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_dir_config', $this->data));
} }
...@@ -110,23 +80,9 @@ class provisionConfig_apache_platform extends provisionConfig_apache { ...@@ -110,23 +80,9 @@ class provisionConfig_apache_platform extends provisionConfig_apache {
/** /**
* Apache site level config class. Virtual host. * Apache site level config class. Virtual host.
*/ */
class provisionConfig_apache_site extends provisionConfig_apache { class provisionConfig_apache_site extends provisionConfig_http_site {
public $template = 'vhost.tpl.php';
public $description = 'apache site configuration file';
function filename() {
return $this->data['http_vhostd_path'] . '/' . $this->uri;
}
function process() { function process() {
if ($this->aliases && !is_array($this->aliases)) { parent::process();
$this->aliases = explode(",", $this->aliases);
}
if (!$this->site_enabled) {
$this->template = 'vhost_disabled.tpl.php';
}
$this->data['extra_config'] = "# Extra configuration from modules:\n"; $this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_vhost_config', $this->uri, $this->data)); $this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_vhost_config', $this->uri, $this->data));
} }
......
...@@ -7,29 +7,88 @@ ...@@ -7,29 +7,88 @@
* The Apache +SSL service implementation. * The Apache +SSL service implementation.
*/ */
// Include the apache service implementation.
// Even though we don't extend it, we do make use of it's config classes.
include_once(dirname(__FILE__) . '../apache/apache_service.inc');
/**
* Apache SSL service class.
*
* This class doesn't extend the apache service itself, so there may
* be some duplication of code between them. The majority of the
* functionality is however implemented in the provisionService_http_public
* class, which we do extend.
*/
class provisionService_http_apache_ssl extends provisionService_http_ssl {
// We share the application name with apache.
protected $application_name = 'apache';
protected $has_restart_cmd = TRUE;
function default_restart_cmd() {
// The apache service defines it's restart command as a static
// method so that we can make use of it here.
return provisionService_http_apache::apache_restart_cmd();
}
class provisionService_http_apache_ssl extends provisionService_http_apache {
public $ssl_enabled = TRUE; public $ssl_enabled = TRUE;
/**
* Initialize the configuration files.
*
* These config classes are a mix of the SSL and Non-SSL apache
* classes. In some cases they extend the Apache classes too.
*/
function init() { function init() {
parent::init(); parent::init();
$this->configs['server'] = array(); // Replace the server config with our own. See the class for more info.
$this->configs['server'][] = 'provisionConfig_apache_server_ssl'; $this->configs['server'][] = 'provisionConfig_apache_server_ssl';
// Just re-use the standard platform config.
$this->configs['platform'][] = 'provisionConfig_apache_platform';
// We generate both an SSL and a non-SSL config file.
$this->configs['site'][] = 'provisionConfig_apache_site';
$this->configs['site'][] = 'provisionConfig_apache_site_ssl'; $this->configs['site'][] = 'provisionConfig_apache_site_ssl';
} }
}
class provisionConfig_apache_server_ssl extends provisionConfig_apache_server { /**
public $template = 'server_ssl.tpl.php'; * Restart apache to pick up the new config files.
*/
function parse_configs() {
return $this->restart();
} }
}
class provisionConfig_apache_site_ssl extends provisionConfig_apache_site { /**
public $template = 'vhost_ssl.tpl.php'; * Server config file for Apache + SSL.
public $description = 'apache ssl configuration file'; *
* This configuration file replaces the Apache server configuration file, but
* inside the template, the original file is once again included.
*
* This config is primarily reponsible for enabling the SSL relation settings,
* so that individual sites can just enable them.
*/
class provisionConfig_apache_server_ssl extends provisionConfig_http_server {
public $template = 'server_ssl.tpl.php';
function filename() { // We use the same extra_config as the apache_server config class.
$this->data['http_vhostd_path'] . '/' . $this->uri . '_ssl'; function process() {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data));
}
} }
/**
* Virtual host config file for Apache + SSL.
*
* This file is created in addition to the existing virtual host,
* and includes some extra directives.
*/
class provisionConfig_apache_ssl_site extends provisionConfig_http_ssl_site {
public $description = 'apache ssl configuration file';
} }
<?php foreach ($ip_addresses as $ip) : ?> <?php foreach ($ip_addresses as $ip) : ?>
NameVirtualHost <?php print $ip . ":" . $http_ssl_port . "\n"; ?> NameVirtualHost <?php print $ip . ":" . $http_ssl_port . "\n"; ?>
<?php endforeach; ?> <?php endforeach; ?>
<IfModule !ssl_module> <IfModule !ssl_module>
LoadModule ssl_module modules/mod_ssl.so LoadModule ssl_module modules/mod_ssl.so
</IfModule> </IfModule>
......
<VirtualHost <?php print "{$ip_address}:{$http_ssl_port}"; ?>>
<?php if ($this->site_mail) : ?>
ServerAdmin <?php print $this->site_mail; ?>
<?php endif;?>
DocumentRoot <?php print $this->root; ?>
ServerName <?php print $this->uri; ?>
SetEnv db_type <?php print urlencode($db_type); ?>
SetEnv db_name <?php print urlencode($db_name); ?>
SetEnv db_user <?php print urlencode($db_user); ?>
SetEnv db_passwd <?php print urlencode($db_passwd); ?>
SetEnv db_host <?php print urlencode($db_host); ?>
SetEnv db_port <?php print urlencode($db_port); ?>
<?php if (!$this->redirection && is_array($this->aliases)) :
foreach ($this->aliases as $alias_url) :
if (trim($alias_url)) : ?>
ServerAlias <?php print $alias_url; ?>
<?php <?php
endif;
endforeach;
endif; ?>
<?php print $extra_config; ?>
# Error handler for Drupal > 4.6.7
<Directory "<?php print $this->site_path; ?>/files">
SetHandler This_is_a_Drupal_security_line_do_not_remove
</Directory>
</VirtualHost>
<?php
// $Id$
/**
* @file
* Configuration classes for the HTTP service.
*/
/**
* Base class for HTTP config files.
*
* This class will publish the config files to remote
* servers automatically.
*/
class provisionConfig_http extends provisionConfig {
function write() {
parent::write();
$this->data['server']->sync($this->filename());
}
function unlink() {
parent::unlink();
$this->data['server']->sync($this->filename());
}
}
/**
* Base configuration class for server level http configs.
*
* This class uses the service defined application_name, to generate
* a top level $app_name.conf for the service.
*
* Each server has it's own configuration, and this class will
* automatically generate a symlink to the correct file for each
* server.
*/
class provisionConfig_http_server extends provisionConfig_http {
public $template = 'server.tpl.php';
public $description = 'web server configuration file';
function write() {
parent::write();
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
// We link the app_name.conf file on the remote server to the right version.
$cmd = sprintf('ln -sf %s %s',
escapeshellarg($this->data['server']->config_path . '/' . $file),
escapeshellarg($this->data['server']->aegir_root . '/config/' . $file)
);
$this->data['server']->shell_exec($cmd);
}
}
function filename() {
if (isset($this->data['application_name'])) {
$file = $this->data['application_name'] . '.conf';
return $this->data['server']->config_path . '/' . $file;
}
else {
return FALSE;
}
}
}
/**
* Base class for platform configuration files.
*/
class provisionConfig_http_platform extends provisionConfig_http {
public $template = 'platform.tpl.php';
public $description = 'platform configuration file';
function filename() {
return $this->data['http_platformd_path'] . '/' . ltrim($this->owner->name, '@') . '.conf';
}
}
/**
* Base class for virtual host configuration files.
*/
class provisionConfig_http_site extends provisionConfig_http {
public $template = 'vhost.tpl.php';
public $description = 'virtual host configuration file';
function filename() {
return $this->data['http_vhostd_path'] . '/' . $this->uri;
}
function process() {
parent::process();
if ($this->aliases && !is_array($this->aliases)) {
$this->aliases = explode(",", $this->aliases);
}
if (!$this->site_enabled) {
$this->template = 'vhost_disabled.tpl.php';
}
}
}
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
include_once(dirname(__FILE__) . '/../provision.service.inc'); include_once(dirname(__FILE__) . '/../provision.service.inc');
function http_provision_services() { function http_provision_services() {
return array('http' => NULL); return array('http' => NULL);
} }
...@@ -14,6 +13,7 @@ class provisionService_http extends provisionService { ...@@ -14,6 +13,7 @@ class provisionService_http extends provisionService {
protected $ssl_enabled = FALSE; protected $ssl_enabled = FALSE;
} }
// Public http service , as in non-encrypted and listening on a port.
class provisionService_http_public extends provisionService_http { class provisionService_http_public extends provisionService_http {
protected $has_port = TRUE; protected $has_port = TRUE;
...@@ -118,5 +118,8 @@ class provisionService_http_public extends provisionService_http { ...@@ -118,5 +118,8 @@ class provisionService_http_public extends provisionService_http {
$this->context->platform->server, $this->context->platform->server,
); );
} }
} }
include_once('http.config.inc');
include_once('http.ssl.inc');
<?php
// $Id$
/**
* @file The base implementation of the SSL capabale web service.
*/
/**
* The base class for SSL supporting servers.
*
* In general, these function the same as normal servers, but have an extra
* port and some extra variables in their templates.
*/
class provisionService_http_ssl extends provisionService_http_public {
protected $ssl_enabled = TRUE;
function default_ssl_port() {
return 443;
}
function init() {
parent::init();
// SSL Port.
$this->server->setProperty('http_ssl_port', $this->default_ssl_port());
// SSL certificate store.
// The certificates are generated from here, and distributed to the servers,
// as needed.
$this->server->ssld_path = "{$this->server->aegir_root}/config/ssl.d";
// SSL certificate store for this server.
// This server's certificates will be stored here.
$this->server->http_ssld_path = "{$this->server->config_path}/ssl.d";
}
function config_data($config = null, $class = null) {
$data = parent::config_data($config, $class);
if ($config == 'site' && $this->context->ssl_enabled) {
if ($ssl_key = $this->context->ssl_key) {
// Retrieve the paths to the cert and key files.
// they are generated if not found.
$certs = $this->get_certificates($ssl_key);
$data = array_merge($data, $certs);
// assign ip address based on ssl_key
$data['ip_address'] = $this->server->ip_addresses[0];
}
}
return $data;
}
/**
* Retrieve an array containing the actual files for this ssl_key.
*
* If the files could not be found, this function will proceed to generate
* certificates for the current site, so that the operation can complete
* succesfully.
*/
function get_certificates($ssl_key) {
$source_path = "{$this->server->ssld_path}/{$ssl_key}";
$certs['ssl_cert_key_source'] = "{$source_path}/openssl.key";
$certs['ssl_cert_source'] = "{$source_path}/openssl.crt";
foreach ($certs as $cert) {
$exists = provision_file()->exists($cert).status();
if (!$exists) {
// if any of the files don't exist, regenerate them.
$this->generate_certificates($ssl_key);
// break out of the loop.
break;
}
}
$path = "{$this->server->http_ssld_path}/{$ssl_key}";
$certs['ssl_cert_key'] = "{$path}/openssl.key";
$certs['ssl_cert'] = "{$path}/openssl.crt";
return $certs;
}
function generate_certificates($ssl_key) {
$path = "{$this->server->ssld_path}/{$ssl_key}";
$created = provision_file()->create_dir($path,
dt("SSL certificate directory for %ssl_key", array(
'%ssl_key' => $ssl_key
)), 0700)->status();
if ($created) {
$pass = 'pass';
// generate a key
drush_shell_exec('openssl genrsa -passout pass:%s -des3 -out %s/openssl.key.orig 1024', $pass, $path);
// unsign it
drush_shell_exec('openssl rsa -passin pass:%s -in %s/openssl.key.orig -out %s/openssl.key', $pass, $path, $path);
// Generate the CSR
$ident = "/C=us/CN={$this->context->uri}/OU={$this->context->uri}/emailAddress=admin@{$this->context->uri}";
drush_shell_exec("openssl req -new -subj '%s' -key %s/openssl.key -out %s/openssl.csr -batch", $ident, $path, $path);
drush_shell_exec("openssl x509 -req -days 365 -in %s/openssl.csr -signkey %s/openssl.key -out %s/openssl.crt", $path, $path, $path);
}
}
function verify() {
if ($this->context->type === 'server') {
provision_file()->create_dir($this->server->ssld_path, dt("Central SSL certificate repository."), 0700);
provision_file()->create_dir($this->server->http_ssld_path,
dt("SSL certificate repository for %server",
array('%server' => $this->server->remote_host)), 0700);
$this->sync($this->server->http_ssld_path, array(
'exclude' => $this->server->http_ssld_path . '/*', // Make sure remote directory is created
));
}
// Call the parent at the end. it will restart the server when it finishes.
parent::verify();
}
}
class provisionConfig_http_ssl_site extends provisionConfig_http_site {
public $template = 'vhost_ssl.tpl.php';
function __construct($owner, $data = array()) {
parent::__construct($owner, $data);
if (!$this->ssl_enabled || !$this->ssl_key) {
//throw new provisionException_continue("SSL has not been enabled for this site. SSL vhost not necessary");
}
}
function filename() {
$this->data['http_vhostd_path'] . '/' . $this->uri . '_ssl';
}
}
...@@ -280,6 +280,5 @@ class provisionConfig_drushrc_site extends provisionConfig_drushrc { ...@@ -280,6 +280,5 @@ class provisionConfig_drushrc_site extends provisionConfig_drushrc {
function filename() { function filename() {
return $this->site_path . '/drushrc.php'; return $this->site_path . '/drushrc.php';
} }
} }
...@@ -355,6 +355,24 @@ class provisionChainedState { ...@@ -355,6 +355,24 @@ class provisionChainedState {
} }
} }
// Base class for provision exceptions.
class provisionException extends Exception {
}
/**
* Signal for parent to continue processing.
*
* The primary use for this class is for the config
* classes to be able to signal to it's caller, that
* the configuration file was not needed, and to
* continue on.
*/
class provisionException_continue extends provisionException {
}
include_once('provision.environment.inc'); include_once('provision.environment.inc');
include_once('provision.service.inc'); include_once('provision.service.inc');
include_once('provision.file.inc'); include_once('provision.file.inc');
......
...@@ -48,14 +48,20 @@ class provisionService extends provisionChainedState { ...@@ -48,14 +48,20 @@ class provisionService extends provisionChainedState {
if (isset($this->configs[$config])) { if (isset($this->configs[$config])) {
// We cast to array here to silently accept the non array version // We cast to array here to silently accept the non array version
foreach ((array) $this->configs[$config] as $class) { foreach ((array) $this->configs[$config] as $class) {
try {
$config = new $class($this->context, $this->config_data($config)); $config = new $class($this->context, $this->config_data($config));
$config->write(); $config->write();
} }
catch (provisionException_continue $e) {
// The service or configuration class has signaled that the config file
// was uneccesary, and we should continue normally.
}
}
} }
} }
/** /**
* Delete a configurationf file. * Delete a configuration file.
* *
* This method will fetch the class to instantiate from the internal * This method will fetch the class to instantiate from the internal
* $this->configs control array. * $this->configs control array.
...@@ -64,9 +70,15 @@ class provisionService extends provisionChainedState { ...@@ -64,9 +70,15 @@ class provisionService extends provisionChainedState {
if (isset($this->configs[$config])) { if (isset($this->configs[$config])) {
// We cast to array here to silently accept the non array version // We cast to array here to silently accept the non array version
foreach ((array) $this->configs[$config] as $class) { foreach ((array) $this->configs[$config] as $class) {
try {
$config = new $class($this->context, $this->config_data($config, $class)); $config = new $class($this->context, $this->config_data($config, $class));
$config->unlink(); $config->unlink();
} }
catch (provisionException_continue $e) {
// The service or configuration class has signaled that the config file
// was uneccesary, and we should continue normally.
}
}
} }
} }
...@@ -75,8 +87,13 @@ class provisionService extends provisionChainedState { ...@@ -75,8 +87,13 @@ class provisionService extends provisionChainedState {
*/ */
function config_data($config = null, $class = null) { function config_data($config = null, $class = null) {
$data = array(); $data = array();
// Always pass the server this service is running on to configs.
$data['server'] = $this->server; $data['server'] = $this->server;
if (!is_null($this->application_name)) {
// This value may be useful to standardize paths in config files.
$data['application_name'] = $this->application_name;
}
return $data; return $data;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment