diff --git a/lib/Exception/CrlGenerationInProgressException.php b/lib/Exception/CrlGenerationInProgressException.php new file mode 100644 index 0000000000..5702e690a5 --- /dev/null +++ b/lib/Exception/CrlGenerationInProgressException.php @@ -0,0 +1,12 @@ +logger->debug('Skipping local CRL generation because source PKI config path is missing', [ 'reason' => $e->getMessage(), ]); - } elseif ($e instanceof \RuntimeException && str_contains($e->getMessage(), 'already in progress')) { + } elseif ($e instanceof CrlGenerationInProgressException) { $this->logger->debug('Local CRL generation is already in progress', [ 'reason' => $e->getMessage(), ]); diff --git a/lib/Service/Crl/CrlService.php b/lib/Service/Crl/CrlService.php index 38ccc6a8e6..289d4cc5a1 100644 --- a/lib/Service/Crl/CrlService.php +++ b/lib/Service/Crl/CrlService.php @@ -15,6 +15,7 @@ use OCA\Libresign\Enum\CertificateEngineType; use OCA\Libresign\Enum\CRLReason; use OCA\Libresign\Enum\CRLStatus; +use OCA\Libresign\Exception\CrlGenerationInProgressException; use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory; use OCA\Libresign\Service\Certificate\FileService; use OCP\ICacheFactory; @@ -414,7 +415,7 @@ private function resolveGeneratedCrlDer(string $instanceId, int $generation, str $lockAcquired = $this->lockCache->add($lockKey, $lockToken, self::GENERATED_CRL_LOCK_TTL); if (!$lockAcquired) { - throw new \RuntimeException(sprintf( + throw new CrlGenerationInProgressException(sprintf( 'CRL %s is already in progress for %s/%d/%s', $forceRefresh ? 'refresh' : 'generation', $instanceId, diff --git a/tests/php/Unit/Service/Crl/CrlRevocationCheckerTest.php b/tests/php/Unit/Service/Crl/CrlRevocationCheckerTest.php index 0363715f60..7c3b5430d0 100644 --- a/tests/php/Unit/Service/Crl/CrlRevocationCheckerTest.php +++ b/tests/php/Unit/Service/Crl/CrlRevocationCheckerTest.php @@ -10,6 +10,7 @@ namespace OCA\Libresign\Tests\Unit\Service\Crl; use OCA\Libresign\Enum\CrlValidationStatus; +use OCA\Libresign\Exception\CrlGenerationInProgressException; use OCA\Libresign\Service\Crl\CrlRevocationChecker; use OCA\Libresign\Service\Crl\CrlService; use OCA\Libresign\Service\Crl\Ldap\LdapCrlDownloader; @@ -543,10 +544,11 @@ public function testBuildValidationCacheKeyDiffersForDifferentCrlContent(): void public function testGenerateLocalCrlLogsDebugWhenAlreadyInProgress(): void { $this->mockCrlRouteUrlGenerator(); + $exception = new CrlGenerationInProgressException('CRL generation is already in progress for abc123/4/o'); $crlService = $this->createMock(CrlService::class); $crlService->expects($this->once()) ->method('generateCrlDer') - ->willThrowException(new \RuntimeException('CRL generation is already in progress for abc123/4/o')); + ->willThrowException($exception); $this->checker->setCrlService($crlService); @@ -555,8 +557,7 @@ public function testGenerateLocalCrlLogsDebugWhenAlreadyInProgress(): void { ->method('debug') ->with( 'Local CRL generation is already in progress', - $this->callback(fn (array $context): bool => isset($context['reason']) - && str_contains($context['reason'], 'already in progress')) + ['reason' => $exception->getMessage()] ); $url = 'https://cloud.example.com/apps/libresign/crl/libresign_abc123_4_o.crl'; @@ -565,4 +566,23 @@ public function testGenerateLocalCrlLogsDebugWhenAlreadyInProgress(): void { $this->assertNull($result); } + public function testGenerateLocalCrlLogsWarningForUntypedExceptionMentioningInProgress(): void { + $this->mockCrlRouteUrlGenerator(); + + $crlService = $this->createMock(CrlService::class); + $crlService->expects($this->once()) + ->method('generateCrlDer') + ->willThrowException(new \RuntimeException('Upstream job is already in progress')); + + $this->checker->setCrlService($crlService); + + $this->logger->expects($this->never())->method('debug'); + $this->logger->expects($this->once())->method('warning'); + + $url = 'https://cloud.example.com/apps/libresign/crl/libresign_abc123_4_o.crl'; + $result = $this->checker->publicGenerateLocalCrl($url); + + $this->assertNull($result); + } + } diff --git a/tests/php/Unit/Service/Crl/CrlServiceTest.php b/tests/php/Unit/Service/Crl/CrlServiceTest.php index 217e5dd5c0..e5c9938cdd 100644 --- a/tests/php/Unit/Service/Crl/CrlServiceTest.php +++ b/tests/php/Unit/Service/Crl/CrlServiceTest.php @@ -14,6 +14,7 @@ use OCA\Libresign\Db\CrlMapper; use OCA\Libresign\Enum\CertificateEngineType; use OCA\Libresign\Enum\CRLReason; +use OCA\Libresign\Exception\CrlGenerationInProgressException; use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory; use OCA\Libresign\Handler\CertificateEngine\IEngineHandler; use OCA\Libresign\Service\Certificate\FileService; @@ -559,8 +560,7 @@ public function testRefreshGeneratedCrlDerThrowsWhenLockHeldAndOnlyReusablePersi $this->certificateEngineFactory->expects($this->never())->method('getEngine'); $this->generatedCrlStorage->expects($this->never())->method('write'); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('CRL refresh is already in progress'); + $this->expectException(CrlGenerationInProgressException::class); $this->service->refreshGeneratedCrlDer('test-instance', 1, 'o'); } @@ -594,8 +594,7 @@ public function testGenerateCrlDerThrowsWhenLockRemainsHeldAndNoReusablePersiste $this->generatedCrlStorage->expects($this->never()) ->method('write'); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('CRL generation is already in progress'); + $this->expectException(CrlGenerationInProgressException::class); $this->service->generateCrlDer('test-instance', 1, 'o'); }