summaryrefslogtreecommitdiffstats
path: root/library/X509/Common
diff options
context:
space:
mode:
Diffstat (limited to 'library/X509/Common')
-rw-r--r--library/X509/Common/Database.php56
-rw-r--r--library/X509/Common/JobOptions.php162
-rw-r--r--library/X509/Common/JobUtils.php77
-rw-r--r--library/X509/Common/Links.php37
4 files changed, 332 insertions, 0 deletions
diff --git a/library/X509/Common/Database.php b/library/X509/Common/Database.php
new file mode 100644
index 0000000..d6eb3e1
--- /dev/null
+++ b/library/X509/Common/Database.php
@@ -0,0 +1,56 @@
+<?php
+
+/* Icinga Web 2 X.509 Module | (c) 2022 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\X509\Common;
+
+use Icinga\Application\Config;
+use Icinga\Data\ResourceFactory;
+use ipl\Sql;
+use PDO;
+
+final class Database
+{
+ /** @var Sql\Connection Database connection */
+ private static $instance;
+
+ private function __construct()
+ {
+ }
+
+ /**
+ * Get the database connection
+ *
+ * @return Sql\Connection
+ */
+ public static function get(): Sql\Connection
+ {
+ if (self::$instance === null) {
+ self::$instance = self::getDb();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Get the connection to the X.509 database
+ *
+ * @return Sql\Connection
+ */
+ private static function getDb(): Sql\Connection
+ {
+ $config = new Sql\Config(ResourceFactory::getResourceConfig(
+ Config::module('x509')->get('backend', 'resource', 'x509')
+ ));
+
+ $options = [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ];
+ if ($config->db === 'mysql') {
+ $options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET SESSION SQL_MODE='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE"
+ . ",NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
+ }
+
+ $config->options = $options;
+
+ return new Sql\Connection($config);
+ }
+}
diff --git a/library/X509/Common/JobOptions.php b/library/X509/Common/JobOptions.php
new file mode 100644
index 0000000..5112272
--- /dev/null
+++ b/library/X509/Common/JobOptions.php
@@ -0,0 +1,162 @@
+<?php
+
+/* Icinga Web 2 X.509 Module | (c) 2023 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\X509\Common;
+
+use DateTime;
+use Exception;
+use Icinga\Module\X509\Job;
+use Icinga\Module\X509\Schedule;
+use InvalidArgumentException;
+use LogicException;
+use stdClass;
+
+trait JobOptions
+{
+ /** @var bool Whether this job should only perform a rescan */
+ protected $rescan;
+
+ /** @var bool Whether this job should perform a full scan */
+ protected $fullScan;
+
+ /** @var ?string Since last scan threshold used to filter out scan targets */
+ protected $sinceLastScan;
+
+ /** @var int Used to control how many targets can be scanned in parallel */
+ protected $parallel = Job::DEFAULT_PARALLEL;
+
+ /** @var Schedule The job schedule config */
+ protected $schedule;
+
+ /**
+ * Get whether this job is performing only a rescan
+ *
+ * @return bool
+ */
+ public function isRescan(): bool
+ {
+ return $this->rescan;
+ }
+
+ /**
+ * Set whether this job should do only a rescan or full scan
+ *
+ * @param bool $rescan
+ *
+ * @return $this
+ */
+ public function setRescan(bool $rescan): self
+ {
+ $this->rescan = $rescan;
+
+ return $this;
+ }
+
+ public function getParallel(): int
+ {
+ return $this->parallel;
+ }
+
+ public function setParallel(int $parallel): self
+ {
+ $this->parallel = $parallel;
+
+ return $this;
+ }
+
+ /**
+ * Set whether this job should scan all known and unknown targets
+ *
+ * @param bool $fullScan
+ *
+ * @return $this
+ */
+ public function setFullScan(bool $fullScan): self
+ {
+ $this->fullScan = $fullScan;
+
+ return $this;
+ }
+
+ /**
+ * Set since last scan threshold for the targets to rescan
+ *
+ * @param ?string $time
+ *
+ * @return $this
+ */
+ public function setLastScan(?string $time): self
+ {
+ if ($time && $time !== 'null') {
+ $sinceLastScan = $time;
+ if ($sinceLastScan[0] !== '-') {
+ // When the user specified "2 days" as a threshold strtotime() will compute the
+ // timestamp NOW() + 2 days, but it has to be NOW() + (-2 days)
+ $sinceLastScan = "-$sinceLastScan";
+ }
+
+ try {
+ // Ensure it's a valid date time string representation.
+ new DateTime($sinceLastScan);
+
+ $this->sinceLastScan = $sinceLastScan;
+ } catch (Exception $_) {
+ throw new InvalidArgumentException(sprintf(
+ 'The specified last scan time is in an unknown format: %s',
+ $time
+ ));
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the targets since last scan threshold
+ *
+ * @return ?DateTime
+ */
+ public function getSinceLastScan(): ?DateTime
+ {
+ if (! $this->sinceLastScan) {
+ return null;
+ }
+
+ return new DateTime($this->sinceLastScan);
+ }
+
+ /**
+ * Get the schedule config of this job
+ *
+ * @return Schedule
+ */
+ public function getSchedule(): Schedule
+ {
+ if (! $this->schedule) {
+ throw new LogicException('You are accessing an unset property. Please make sure to set it beforehand.');
+ }
+
+ return $this->schedule;
+ }
+
+ /**
+ * Set the schedule config of this job
+ *
+ * @param Schedule $schedule
+ *
+ * @return $this
+ */
+ public function setSchedule(Schedule $schedule): self
+ {
+ $this->schedule = $schedule;
+
+ /** @var stdClass $config */
+ $config = $schedule->getConfig();
+ $this->setFullScan($config->full_scan ?? false);
+ $this->setRescan($config->rescan ?? false);
+ $this->setLastScan($config->since_last_scan ?? Job::DEFAULT_SINCE_LAST_SCAN);
+
+ return $this;
+ }
+}
diff --git a/library/X509/Common/JobUtils.php b/library/X509/Common/JobUtils.php
new file mode 100644
index 0000000..54398fe
--- /dev/null
+++ b/library/X509/Common/JobUtils.php
@@ -0,0 +1,77 @@
+<?php
+
+// Icinga Web 2 X.509 Module | (c) 2022 Icinga GmbH | GPLv2
+
+namespace Icinga\Module\X509\Common;
+
+use GMP;
+use Icinga\Application\Logger;
+use ipl\Stdlib\Str;
+
+trait JobUtils
+{
+ /**
+ * Parse the given comma separated CIDRs
+ *
+ * @param string $cidrs
+ *
+ * @return array<string, array<int, int|string>>
+ */
+ public function parseCIDRs(string $cidrs): array
+ {
+ $result = [];
+ foreach (Str::trimSplit($cidrs) as $cidr) {
+ $pieces = Str::trimSplit($cidr, '/');
+ if (count($pieces) !== 2) {
+ Logger::warning('CIDR %s is in the wrong format', $cidr);
+ continue;
+ }
+
+ $result[$cidr] = $pieces;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Parse the given comma separated ports
+ *
+ * @param string $ports
+ *
+ * @return array<int, array<string>>
+ */
+ public function parsePorts(string $ports): array
+ {
+ $result = [];
+ foreach (Str::trimSplit($ports) as $portRange) {
+ $pieces = Str::trimSplit($portRange, '-');
+ if (count($pieces) === 2) {
+ list($start, $end) = $pieces;
+ } else {
+ $start = $pieces[0];
+ $end = $pieces[0];
+ }
+
+ $result[] = [$start, $end];
+ }
+
+ return $result;
+ }
+
+ /**
+ * Parse the given comma separated excluded targets
+ *
+ * @param ?string $excludes
+ *
+ * @return array<string>
+ */
+ public function parseExcludes(?string $excludes): array
+ {
+ $result = [];
+ if (! empty($excludes)) {
+ $result = array_flip(Str::trimSplit($excludes));
+ }
+
+ return $result;
+ }
+}
diff --git a/library/X509/Common/Links.php b/library/X509/Common/Links.php
new file mode 100644
index 0000000..c1570dc
--- /dev/null
+++ b/library/X509/Common/Links.php
@@ -0,0 +1,37 @@
+<?php
+
+/* Icinga Web 2 X.509 Module | (c) 2023 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\X509\Common;
+
+use Icinga\Module\X509\Model\X509Job;
+use Icinga\Module\X509\Model\X509Schedule;
+use ipl\Web\Url;
+
+class Links
+{
+ public static function job(X509Job $job): Url
+ {
+ return Url::fromPath('x509/job', ['id' => $job->id]);
+ }
+
+ public static function updateJob(X509Job $job): Url
+ {
+ return Url::fromPath('x509/job/update', ['id' => $job->id]);
+ }
+
+ public static function schedules(X509Job $job): Url
+ {
+ return Url::fromPath('x509/job/schedules', ['id' => $job->id]);
+ }
+
+ public static function scheduleJob(X509Job $job): Url
+ {
+ return Url::fromPath('x509/job/schedule', ['id' => $job->id]);
+ }
+
+ public static function updateSchedule(X509Schedule $schedule): Url
+ {
+ return Url::fromPath('x509/job/update-schedule', ['id' => $schedule->job->id, 'scheduleId' => $schedule->id]);
+ }
+}