View source
<?php
class Provision_Service_Certificate_LetsEncrypt extends Provision_Service_Certificate {
public $service = 'LetsEncrypt';
function init_server() {
parent::init_server();
$this->configs['server'][] = 'Provision_Config_LetsEncrypt';
$this->server
->setProperty('letsencrypt_ca', 'staging');
$this->server->letsencrypt_script_path = $this->server->aegir_root . '/config/letsencrypt';
$this->server->letsencrypt_config_path = $this->server->aegir_root . '/config/letsencrypt.d';
$this->server->letsencrypt_challenge_path = $this->server->aegir_root . '/config/letsencrypt.d/well-known/acme-challenge';
}
function config_data($config = null, $class = null) {
$data = parent::config_data($config, $class);
$data['letsencrypt_current_time'] = date(DATE_COOKIE, time());
return $data;
}
function get_source_path($https_key) {
return "{$this->server->letsencrypt_config_path}/{$https_key}";
}
function get_certificates($https_key) {
$certs = parent::get_certificates($https_key);
return $certs;
}
function get_certificate_paths($https_key) {
$source_path = $this
->get_source_path($https_key);
$target_path = "{$this->server->http_ssld_path}/{$https_key}";
$certs = array();
$certs['https_cert_key_source'] = "{$source_path}/privkey.pem";
$certs['https_cert_key'] = "{$target_path}/openssl.key";
$certs['https_cert_source'] = "{$source_path}/fullchain.pem";
$certs['https_cert'] = "{$target_path}/openssl.crt";
return $certs;
}
function generate_certificates($https_key) {
$path = $this
->get_source_path($https_key);
provision_file()
->create_dir($path, dt("HTTPS certificate directory for %https_key", array(
'%https_key' => $https_key,
)), 0700);
$config_file = $this
->getConfigFile($this->server->letsencrypt_ca);
$script_path = $this->server->letsencrypt_script_path;
$config_path = $this->server->letsencrypt_config_path;
$drush_alias = escapeshellarg('@' . d()->uri);
$domain_list = $this
->getDomainsString(d());
$on_remote_server = !provision_is_local_host(d()->platform->web_server->remote_host);
$le_hook = $script_path . '/dehydrated-hooks.sh';
$le_options = '--cron --accept-terms';
if ($on_remote_server) {
$le_options .= ' --hook ' . $le_hook;
}
drush_log(dt("Generating Let's Encrypt certificates."));
$cmd = "AEGIR_DRUSH_ALIAS={$drush_alias} {$script_path}/script {$le_options} --config {$script_path}/{$config_file} --out {$config_path} {$domain_list}";
drush_log("Running: " . $cmd, 'notice');
$result = drush_shell_exec($cmd);
if ($result) {
foreach (drush_shell_exec_output() as $line) {
drush_log($line);
}
drush_log(dt("Successfully generated Let's Encrypt certificates."), 'success');
}
else {
foreach (drush_shell_exec_output() as $line) {
drush_log($line, 'warning');
}
if (drush_get_option('hosting_https_fail_task_if_certificate_fails', FALSE)) {
drush_set_error('HTTPS_CERT_GEN_FAIL', dt("Failed to generate Let's Encrypt certificates."));
}
else {
drush_log(dt("Failed to generate Let's Encrypt certificates."), 'warning');
}
}
}
protected function getConfigFile($environment) {
if ($environment == 'production') {
return 'config';
}
return 'config.staging';
}
protected function getDomainsString($context) {
$canonical_name = $context->uri;
$options_list = array(
"--domain {$canonical_name}",
);
if (isset($context->aliases)) {
foreach ($context->aliases as $alias) {
if (!in_array("--domain {$alias}", $options_list)) {
$options_list[] = "--domain {$alias}";
}
}
}
return implode(" ", $options_list);
}
function verify() {
parent::verify();
if ($this->context->type == 'server') {
$source = dirname(dirname(dirname(dirname(__FILE__)))) . '/bin';
provision_file()
->create_dir($this->server->letsencrypt_config_path, dt("Let's Encrypt configuration directory"), 0711);
provision_file()
->create_dir($this->server->letsencrypt_challenge_path, dt("Let's Encrypt ACME challenge directory"), 0711);
provision_file()
->create_dir($this->server->letsencrypt_script_path, dt("Let's Encrypt script + data directory"), 0711);
provision_file()
->copy($source . '/config', $this->server->letsencrypt_script_path . '/config');
provision_file()
->copy($source . '/config.staging', $this->server->letsencrypt_script_path . '/config.staging');
provision_file()
->copy($source . '/dehydrated-hooks.sh', $this->server->letsencrypt_script_path . '/dehydrated-hooks.sh');
provision_file()
->chmod($this->server->letsencrypt_script_path . '/dehydrated-hooks.sh', 0755);
if (drush_copy_dir($source . '/dehydrated', $this->server->letsencrypt_script_path . '/dehydrated', FILE_EXISTS_OVERWRITE)) {
drush_log("Copied Let's Encrypt dehydrated script code into place.", 'success');
}
provision_file()
->chmod($this->server->letsencrypt_script_path . '/dehydrated/dehydrated', 0755);
provision_file()
->symlink($this->server->letsencrypt_script_path . '/dehydrated/dehydrated', $this->server->letsencrypt_script_path . '/script', dt("Create Let's Encrypt dehydrated symlink."), 0644);
}
}
}