diff --git a/modules/cron/bin/cron.php b/modules/cron/bin/cron.php new file mode 100755 index 0000000000000000000000000000000000000000..073c278cbea20179f238d99e5477a11acf568ce8 --- /dev/null +++ b/modules/cron/bin/cron.php @@ -0,0 +1,45 @@ +#!/usr/bin/env php +<?php + +/* + * This script can be used to invoke cron jobs from cli. + * You most likely want to execute as the user running your webserver. + * Example: su -s "/bin/sh" -c "php /var/simplesamlphp/modules/cron/bin/cron.php -t hourly" apache + */ + +// This is the base directory of the SimpleSAMLphp installation +$baseDir = dirname(dirname(dirname(dirname(__FILE__)))); + +// Add library autoloader. +require_once($baseDir . '/lib/_autoload.php'); + +if (!SimpleSAML\Module::isModuleEnabled('cron')) { + echo("You need to enable the cron module before this script can be used.\n"); + echo("You can enable it by running the following command:\n"); + echo(' echo >"' . $baseDir . '/modules/cron/enable' . "\"\n"); + exit(1); +} + +$options = getopt("t:"); +if (function_exists('posix_getuid') && posix_getuid() === 0) { + echo "Running as root is discouraged. Some cron jobs will generate files that would have the wrong ownership.\n"; + echo 'Suggested invocation: su -s "/bin/sh" -c "php /var/simplesamlphp/modules/cron/bin/cron.php -t hourly" apache'; + exit(3); +} + +if (!array_key_exists('t', $options)) { + echo "You must provide a tag (-t) option"; + exit(2); +} + +$tag = $options['t']; +$cron = new SimpleSAML\Module\cron\Cron(); +if (!$cron->isValidTag($tag)) { + echo "Invalid tag option '$tag'.\n"; + exit(2); +} + +$cronInfo = $cron->runTag($tag); + +print_r($cronInfo); +exit(0); diff --git a/modules/cron/docs/cron.md b/modules/cron/docs/cron.md index d75db3b8c83297992760adac349b2dd6753a6177..88630a29b3584d5e3947e3a882fa2b066596ec79 100644 --- a/modules/cron/docs/cron.md +++ b/modules/cron/docs/cron.md @@ -47,9 +47,17 @@ here is a random key available to no one but you. Additionally, make sure that you include here the appropriate tags - for example any tags that you previously told metarefresh to use in the `cron` directive. -Triggering Cron via HTTP +Triggering Cron --------------------------- +You can trigger the cron hooks through HTTP or CLI. The HTTP method +is the original technique, and it is recommended if you don't need to +trigger CPU or memory intensive cron hooks. The CLI option is +recommended if you need more control over memory, CPU limits and +process priority. + +### With HTTP + `cron` functionality can be invoked by making an HTTP request to the cron module. Use your web browser to go to `https://YOUR_SERVER/simplesaml/module.php/cron/croninfo.php`. Make @@ -80,3 +88,35 @@ follow the appropriate links to execute the cron jobs you want. The page will take a while loading, and eventually show a blank page. +### With CLI + +You can invoke cron functionality by running +`/var/simplesamlphp/modules/cron/bin/cron.php` and providing a tag +with the `-t ` argument. + +It is strongly recommended that you run the cron cli script as the +same user as the web server. Several cron hooks created files and +those files may have the wrong permissions if you run the job as root. + +**note:** Logging behavior in SSP when running from CLI varies by +version. The latest version logs to PHP's error log and ignores any +logging configuration from `config.php` + +Below is an example of invoking the script. It will: + +* Run a command as the `apache` user + * `-s` specifies `apache` user's shell, since the default is non-interactive +* Override INI entries to increase memory and execution time. + * This allows for processing large metadata files in metarefresh +* Run the `cron.php` script with the `hourly` tag +* Use `nice` to lower the priority below that of web server processes + +```bash +su -s "/bin/sh" \ + -c "nice -n 10 \ + php -d max_execution_time=120 -d memory_limit=600M \ + /var/simplesamlphp/modules/cron/bin/cron.php -t hourly" \ + apache + +``` + diff --git a/modules/cron/lib/Cron.php b/modules/cron/lib/Cron.php new file mode 100644 index 0000000000000000000000000000000000000000..b2532e75fa098ce6892c37287d64462bc366e56b --- /dev/null +++ b/modules/cron/lib/Cron.php @@ -0,0 +1,63 @@ +<?php + +namespace SimpleSAML\Module\cron; + +/** + * Handles interactions with SSP's cron system/hooks. + */ +class Cron +{ + /** + * The configuration for the Cron module + * @var \SimpleSAML_Configuration + */ + private $cronconfig; + + /* + * @param \SimpleSAML_Configuration $cronconfig The cron configuration to use. If not specified defaults + * to `config/module_cron.php` + */ + public function __construct(\SimpleSAML_Configuration $cronconfig = null) + { + if ($cronconfig == null) { + $cronconfig = \SimpleSAML_Configuration::getConfig('module_cron.php'); + } + $this->cronconfig = $cronconfig; + } + + /** + * Invoke the cron hook for the given tag + * @param $tag string The tag to use. Must be valid in the cronConfig + * @return array the tag, and summary information from the run. + * @throws Exception If an invalid tag specified + */ + public function runTag($tag) + { + + if (!$this->isValidTag($tag)) { + throw new \Exception("Invalid cron tag '$tag''"); + } + + $summary = array(); + $croninfo = array( + 'summary' => &$summary, + 'tag' => $tag, + ); + + \SimpleSAML\Module::callHooks('cron', $croninfo); + + foreach ($summary as $s) { + \SimpleSAML\Logger::debug('Cron - Summary: ' . $s); + } + + return $croninfo; + } + + public function isValidTag($tag) + { + if (!is_null($this->cronconfig->getValue('allowed_tags'))) { + return in_array($tag, $this->cronconfig->getArray('allowed_tags')); + } + return true; + } +} diff --git a/modules/cron/www/cron.php b/modules/cron/www/cron.php index 79d0472ff08ece30cb8377cc4d7bff3ee94dcf74..4f22fc5df0b111403d9fd6e119264a8d083b04f2 100644 --- a/modules/cron/www/cron.php +++ b/modules/cron/www/cron.php @@ -9,27 +9,19 @@ if (!is_null($cronconfig->getValue('key'))) { exit; } } -if (!is_null($cronconfig->getValue('allowed_tags'))) { - if (!in_array($_REQUEST['tag'], $cronconfig->getValue('allowed_tags'))) { - SimpleSAML\Logger::error('Cron - Illegal tag [' . $_REQUEST['tag'] . '].'); - exit; - } + +$cron = new SimpleSAML\Module\cron\Cron(); +if (!$cron->isValidTag($_REQUEST['tag'])) { + SimpleSAML\Logger::error('Cron - Illegal tag [' . $_REQUEST['tag'] . '].'); + exit; } -$summary = array(); -$croninfo = array( - 'summary' => &$summary, - 'tag' => $_REQUEST['tag'], -); $url = \SimpleSAML\Utils\HTTP::getSelfURL(); $time = date(DATE_RFC822); -SimpleSAML\Module::callHooks('cron', $croninfo); - -foreach ($summary AS $s) { - SimpleSAML\Logger::debug('Cron - Summary: ' . $s); -} +$croninfo = $cron->runTag($_REQUEST['tag']); +$summary = $croninfo['summary']; if ($cronconfig->getValue('sendemail', TRUE) && count($summary) > 0) {