From 14748bbedb3bd971bcbf6fcd130e6ed5d55b18aa Mon Sep 17 00:00:00 2001 From: mborne Date: Sun, 24 Mar 2024 11:46:59 +0100 Subject: [PATCH] chore(trivy): add TRIVY_ENABLED option and improve checkers logs (refs #28) --- .github/workflows/ci.yml | 1 + README.md | 7 +++--- config/services.yaml | 2 ++ src/Git/Analyzer.php | 16 +++++++++----- src/Git/Checker/LicenseChecker.php | 11 ++++++++++ src/Git/Checker/ReadmeChecker.php | 10 +++++++++ src/Git/Checker/TrivyChecker.php | 35 +++++++++++++++++++++++++++++- 7 files changed, 73 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdea5a3..014e580 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,7 @@ jobs: XDEBUG_MODE: coverage SYMFONY_DEPRECATIONS_HELPER: weak GIT_MANAGER_DIR: /tmp/git-manager-test + TRIVY_ENABLED: false - name: Upload coverage results to coveralls.io if: github.ref == 'refs/heads/master' && matrix.php-version == '8.2' diff --git a/README.md b/README.md index 85b4d49..6d72a22 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,10 @@ CLI helpers to manage a set of git repositories. ## Parameters -| Name | Description | Default | -| ----------------- | ------------------------------------- | ------------------ | -| `GIT_MANAGER_DIR` | Directory containing git repositories | `/var/git-manager` | +| Name | Description | Default | +| ----------------- | ------------------------------------- | ----------------------- | +| `GIT_MANAGER_DIR` | Directory containing git repositories | `{projectDir}/var/data` | +| `TRIVY_ENABLED` | Enable/disable trivy scan | `true` | ## Setup diff --git a/config/services.yaml b/config/services.yaml index 12c3145..b1e4877 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,5 +1,6 @@ parameters: env(GIT_MANAGER_DIR): '%kernel.project_dir%/var/data' + env(TRIVY_ENABLED): 'true' services: _defaults: @@ -8,6 +9,7 @@ services: public: false bind: $dataDir: '%env(GIT_MANAGER_DIR)%' + $trivyEnabled: '%env(bool:TRIVY_ENABLED)%' MBO\GitManager\: resource: '../src/*' diff --git a/src/Git/Analyzer.php b/src/Git/Analyzer.php index 3e9663b..d627146 100644 --- a/src/Git/Analyzer.php +++ b/src/Git/Analyzer.php @@ -6,6 +6,7 @@ use MBO\GitManager\Git\Checker\LicenseChecker; use MBO\GitManager\Git\Checker\ReadmeChecker; use MBO\GitManager\Git\Checker\TrivyChecker; +use Psr\Log\LoggerInterface; /** * Analyze git repository to provide informations. @@ -17,12 +18,14 @@ class Analyzer */ private $checkers; - public function __construct() - { + public function __construct( + bool $trivyEnabled, + private LoggerInterface $logger + ) { $this->checkers = [ - new ReadmeChecker(), - new LicenseChecker(), - new TrivyChecker(), + new ReadmeChecker($logger), + new LicenseChecker($logger), + new TrivyChecker($trivyEnabled, $logger), ]; } @@ -33,6 +36,9 @@ public function __construct() */ public function getMetadata(GitRepository $gitRepository): array { + $this->logger->debug('[Analyser] retrieve git metadata...', [ + 'repository' => $gitRepository->getWorkingDir(), + ]); $metadata = [ 'size' => $gitRepository->getSize() * 1024, ]; diff --git a/src/Git/Checker/LicenseChecker.php b/src/Git/Checker/LicenseChecker.php index 697b5bf..d8ced1b 100644 --- a/src/Git/Checker/LicenseChecker.php +++ b/src/Git/Checker/LicenseChecker.php @@ -4,12 +4,17 @@ use Gitonomy\Git\Repository as GitRepository; use MBO\GitManager\Git\CheckerInterface; +use Psr\Log\LoggerInterface; /** * Ensure that LICENSE file is present. */ class LicenseChecker implements CheckerInterface { + public function __construct(private LoggerInterface $logger) + { + } + public const LICENSE_FILENAMES = [ 'LICENSE', 'LICENSE.md', @@ -22,6 +27,12 @@ public function getName(): string public function check(GitRepository $gitRepository): bool|string { + $this->logger->debug('[{checker}] look for license file...', [ + 'checker' => $this->getName(), + 'repository' => $gitRepository->getWorkingDir(), + 'expected' => static::LICENSE_FILENAMES, + ]); + $workingDir = $gitRepository->getWorkingDir(); foreach (static::LICENSE_FILENAMES as $filename) { $expectedPath = $workingDir.DIRECTORY_SEPARATOR.$filename; diff --git a/src/Git/Checker/ReadmeChecker.php b/src/Git/Checker/ReadmeChecker.php index 18be2ab..8d4782a 100644 --- a/src/Git/Checker/ReadmeChecker.php +++ b/src/Git/Checker/ReadmeChecker.php @@ -4,12 +4,17 @@ use Gitonomy\Git\Repository as GitRepository; use MBO\GitManager\Git\CheckerInterface; +use Psr\Log\LoggerInterface; /** * Ensure that README file is present. */ class ReadmeChecker implements CheckerInterface { + public function __construct(private LoggerInterface $logger) + { + } + public function getName(): string { return 'readme'; @@ -17,6 +22,11 @@ public function getName(): string public function check(GitRepository $gitRepository): bool { + $this->logger->debug('[{checker}] look for README.md file...', [ + 'checker' => $this->getName(), + 'repository' => $gitRepository->getWorkingDir(), + ]); + $workingDir = $gitRepository->getWorkingDir(); $readmePath = $workingDir.DIRECTORY_SEPARATOR.'README.md'; diff --git a/src/Git/Checker/TrivyChecker.php b/src/Git/Checker/TrivyChecker.php index 983f696..e6993bf 100644 --- a/src/Git/Checker/TrivyChecker.php +++ b/src/Git/Checker/TrivyChecker.php @@ -4,6 +4,7 @@ use Gitonomy\Git\Repository as GitRepository; use MBO\GitManager\Git\CheckerInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; @@ -14,6 +15,15 @@ class TrivyChecker implements CheckerInterface { public const SEVERITIES = ['HIGH', 'CRITICAL']; + private bool $enabled; + + public function __construct( + bool $trivyEnabled, + private LoggerInterface $logger + ) { + $this->enabled = $trivyEnabled && $this->isAvailable(); + } + public function getName(): string { return 'trivy'; @@ -22,6 +32,21 @@ public function getName(): string public function check(GitRepository $gitRepository): mixed { $workingDir = $gitRepository->getWorkingDir(); + + if (!$this->enabled) { + $this->logger->debug('[{checker}] skipped (disabled)', [ + 'checker' => $this->getName(), + 'repository' => $workingDir, + ]); + + return null; + } + + $this->logger->debug('[{checker}] run trivy fs on repository...', [ + 'checker' => $this->getName(), + 'repository' => $workingDir, + ]); + $trivyReportPath = $workingDir.'/.trivy.json'; $process = new Process([ 'trivy', @@ -105,10 +130,18 @@ public function getSummary(array $vulnerabilities): array public function isAvailable(): bool { try { - $this->getVersion(); + $version = $this->getVersion(); + $this->logger->info('[{checker}] trivy executable found (version={trivy_version})', [ + 'checker' => $this->getName(), + 'trivy_version' => $version, + ]); return true; } catch (\Exception $e) { + $this->logger->warning('[{checker}] trivy not found, scan disabled', [ + 'checker' => $this->getName(), + ]); + return false; } }