From 0f0dd91246486fc25e48e04f7f1e9107124e8f69 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 9 Jul 2019 07:50:11 +0200 Subject: [PATCH] combine Let's Encrypt cron with webserver-vhost-generation but allow manually execution using --debug/--force Signed-off-by: Michael Kaufmann --- lib/Froxlor/Cron/CronConfig.php | 1 + lib/Froxlor/Cron/Http/HttpConfigBase.php | 10 +++++ lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php | 45 ++++++++++++-------- lib/Froxlor/Cron/MasterCron.php | 1 + lib/Froxlor/Cron/System/TasksCron.php | 1 + 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/lib/Froxlor/Cron/CronConfig.php b/lib/Froxlor/Cron/CronConfig.php index e5916ed0..18b2f8d8 100644 --- a/lib/Froxlor/Cron/CronConfig.php +++ b/lib/Froxlor/Cron/CronConfig.php @@ -61,6 +61,7 @@ class CronConfig $month_delay = 7; while ($row_cronentry = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { // create cron.d-entry + $matches = array(); if (preg_match("/(\d+) (MINUTE|HOUR|DAY|WEEK|MONTH)/", $row_cronentry['interval'], $matches)) { if ($matches[1] == 1) { $minvalue = "*"; diff --git a/lib/Froxlor/Cron/Http/HttpConfigBase.php b/lib/Froxlor/Cron/Http/HttpConfigBase.php index 3deeb8f0..e5b68629 100644 --- a/lib/Froxlor/Cron/Http/HttpConfigBase.php +++ b/lib/Froxlor/Cron/Http/HttpConfigBase.php @@ -28,6 +28,16 @@ use Froxlor\Cron\Http\Php\Fpm; class HttpConfigBase { + public function init() + { + // if Let's Encrypt is activated, run it before regeneration of webserver configfiles + if (Settings::Get('system.leenabled') == 1) { + \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, 'Running Let\'s Encrypt cronjob prior to regenerating webserver config files'); + \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::$no_inserttask = true; + \Froxlor\Cron\Http\LetsEncrypt\AcmeSh::run(); + } + } + public function reload() { $called_class = get_called_class(); diff --git a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php index 70b398fc..98762abb 100644 --- a/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php +++ b/lib/Froxlor/Cron/Http/LetsEncrypt/AcmeSh.php @@ -43,13 +43,19 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static $do_update = true; + public static $no_inserttask = false; + public static function run() { + if (! defined('CRON_IS_FORCED') && ! defined('CRON_DEBUG_FLAG')) { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Let's Encrypt cronjob is combined with regeneration of webserver configuration files.\nFor debugging purposes you can use the --debug switch and/or the --force switch to run the cron manually."); + } + self::checkInstall(); self::$apiserver = 'https://acme-v0' . \Froxlor\Settings::Get('system.leapiversion') . '.api.letsencrypt.org/directory'; - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating Let's Encrypt certificates"); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Requesting/renewing Let's Encrypt certificates"); $certificates_stmt = Database::query(" SELECT @@ -174,7 +180,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron ); $froxlor_aliases = Settings::Get('system.froxloraliases'); - if (!empty($froxlor_aliases)) { + if (! empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); foreach ($froxlor_aliases as $falias) { if (\Froxlor\Validate\Validate::validateDomain(trim($falias))) { @@ -186,9 +192,9 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron // Only renew let's encrypt certificate if no broken ssl_redirect is enabled // - this temp. deactivation of the ssl-redirect is handled by the webserver-cronjob if ($cert_mode == 'renew') { - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']); } else { - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); } $cronlog = FroxlorLogger::getInstanceOf(array( @@ -216,18 +222,18 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron if (! empty($certrow['ssl_cert_file'])) { $cert_mode = 'renew'; - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updating certificate for " . $certrow['domain']); } else { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Creating certificate for " . $certrow['domain']); } - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $certrow['domain']); $domains = array( $certrow['domain'] ); // add www. to SAN list if ($certrow['wwwserveralias'] == 1) { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $certrow['domain']); $domains[] = 'www.' . $certrow['domain']; } @@ -237,27 +243,30 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron )); $aliasdomains = $aliasdomains_stmt->fetchAll(\PDO::FETCH_ASSOC); foreach ($aliasdomains as $aliasdomain) { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: " . $aliasdomain['domain']); $domains[] = $aliasdomain['domain']; if ($aliasdomain['wwwserveralias'] == 1) { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Adding SAN entry: www." . $aliasdomain['domain']); $domains[] = 'www.' . $aliasdomain['domain']; } } self::runAcmeSh($certrow, $domains, $cert_mode, $cronlog, $changedetected); } else { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); } } // If we have a change in a certificate, we need to update the webserver - configs // This is easiest done by just creating a new task ;) if ($changedetected) { - \Froxlor\System\Cronjob::inserttask(1); + if (self::$no_inserttask == false) { + \Froxlor\System\Cronjob::inserttask(1); + } + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated"); + } else { + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificates due for renewal found"); } - - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated"); } private static function runAcmeSh($certrow = array(), $domains = array(), $cert_mode = 'issue', &$cronlog = null, &$changedetected = 0) @@ -314,10 +323,10 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron )); } - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']); $changedetected = 1; } else { - $cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); + $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); } } } @@ -342,7 +351,7 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static function checkInstall() { if (! file_exists(self::$acmesh)) { - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/"); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Could not find acme.sh - installing it to /root/.acme.sh/"); $return = false; \Froxlor\FileDir::safe_exec("wget -O - https://get.acme.sh | sh", $return, array( '|' @@ -353,6 +362,6 @@ class AcmeSh extends \Froxlor\Cron\FroxlorCron private static function checkUpgrade() { $acmesh_result = \Froxlor\FileDir::safe_exec(self::$acmesh . " --upgrade"); - FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result)); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Checking for LetsEncrypt client upgrades before renewing certificates:\n" . implode("\n", $acmesh_result)); } } diff --git a/lib/Froxlor/Cron/MasterCron.php b/lib/Froxlor/Cron/MasterCron.php index 861f6522..18839df2 100644 --- a/lib/Froxlor/Cron/MasterCron.php +++ b/lib/Froxlor/Cron/MasterCron.php @@ -70,6 +70,7 @@ class MasterCron extends \Froxlor\Cron\FroxlorCron // also regenerate cron.d-file \Froxlor\System\Cronjob::inserttask('99'); array_push($jobs_to_run, 'tasks'); + define('CRON_IS_FORCED', 1); } elseif (strtolower($argv[$x]) == '--debug') { define('CRON_DEBUG_FLAG', 1); } elseif (strtolower($argv[$x]) == '--no-fork') { diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php index 2ceb1db9..7dc2a4f2 100644 --- a/lib/Froxlor/Cron/System/TasksCron.php +++ b/lib/Froxlor/Cron/System/TasksCron.php @@ -145,6 +145,7 @@ class TasksCron extends \Froxlor\Cron\FroxlorCron $webserver = new $websrv(); if (isset($webserver)) { + $webserver->init(); $webserver->createIpPort(); $webserver->createVirtualHosts(); $webserver->createFileDirOptions();