From 530acfb26e0ca5cf724c1bfb4c71345aa4c59ded Mon Sep 17 00:00:00 2001
From: Patrick Radtke <patrick@cirrusidentity.com>
Date: Fri, 25 Aug 2017 14:41:49 -0700
Subject: [PATCH] Allow CLI invocation of Cron

---
 modules/cron/bin/cron.php | 45 +++++++++++++++++++++++++++++
 modules/cron/lib/Cron.php | 61 +++++++++++++++++++++++++++++++++++++++
 modules/cron/www/cron.php | 21 ++++----------
 3 files changed, 112 insertions(+), 15 deletions(-)
 create mode 100644 modules/cron/bin/cron.php
 create mode 100644 modules/cron/lib/Cron.php

diff --git a/modules/cron/bin/cron.php b/modules/cron/bin/cron.php
new file mode 100644
index 000000000..6bafc78a3
--- /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 (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 sspmod_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/lib/Cron.php b/modules/cron/lib/Cron.php
new file mode 100644
index 000000000..40390329b
--- /dev/null
+++ b/modules/cron/lib/Cron.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * Handles interactions with SSP's cron system/hooks.
+ */
+class sspmod_cron_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 79d0472ff..6ca986e7a 100644
--- a/modules/cron/www/cron.php
+++ b/modules/cron/www/cron.php
@@ -9,27 +9,18 @@ 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 sspmod_cron_Cron($cronconfig);
+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']);
 
 if ($cronconfig->getValue('sendemail', TRUE) && count($summary) > 0) {
 
-- 
GitLab