diff options
Diffstat (limited to 'library/X509/Common')
-rw-r--r-- | library/X509/Common/Database.php | 56 | ||||
-rw-r--r-- | library/X509/Common/JobOptions.php | 162 | ||||
-rw-r--r-- | library/X509/Common/JobUtils.php | 77 | ||||
-rw-r--r-- | library/X509/Common/Links.php | 37 |
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]); + } +} |