Skip to content

Commit 22b5d9e

Browse files
committed
feat: allow custom backend uris
Closes #14
1 parent 242ca71 commit 22b5d9e

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

Classes/Http/CspHeaderMiddleware.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
namespace Flowpack\ContentSecurityPolicy\Http;
66

7-
use Exception;
87
use Flowpack\ContentSecurityPolicy\Exceptions\DirectivesNormalizerException;
98
use Flowpack\ContentSecurityPolicy\Exceptions\InvalidDirectiveException;
109
use Flowpack\ContentSecurityPolicy\Factory\PolicyFactory;
1110
use Flowpack\ContentSecurityPolicy\Helpers\TagHelper;
1211
use Flowpack\ContentSecurityPolicy\Model\Nonce;
1312
use Flowpack\ContentSecurityPolicy\Model\Policy;
1413
use GuzzleHttp\Psr7\Utils;
14+
use InvalidArgumentException;
1515
use Neos\Flow\Annotations as Flow;
1616
use Psr\Http\Message\ResponseInterface;
1717
use Psr\Http\Message\ServerRequestInterface;
1818
use Psr\Http\Server\MiddlewareInterface;
1919
use Psr\Http\Server\RequestHandlerInterface;
20+
use Psr\Log\LoggerInterface;
2021

2122
class CspHeaderMiddleware implements MiddlewareInterface
2223
{
@@ -49,6 +50,17 @@ class CspHeaderMiddleware implements MiddlewareInterface
4950
*/
5051
protected array $policies;
5152

53+
// TODO: rename to throw-on-configuration-error in next major version
54+
/**
55+
* @Flow\InjectConfiguration(path="throw-invalid-directive-exception")
56+
*/
57+
protected bool $throwInvalidDirectiveException;
58+
59+
/**
60+
* @Flow\Inject
61+
*/
62+
protected LoggerInterface $logger;
63+
5264
/**
5365
* @inheritDoc
5466
* @throws InvalidDirectiveException
@@ -87,7 +99,16 @@ private function getPolicyByCurrentContext(ServerRequestInterface $request): Pol
8799
);
88100

89101
foreach ($backendUris as $pattern) {
90-
if (preg_match('#' . $pattern . '#', $path)) {
102+
$result = preg_match('#' . str_replace('#', '\#', $pattern) . '#', $path);
103+
if ($result === false) {
104+
$message = sprintf('Invalid matchUri pattern "%s": %s', $pattern, preg_last_error_msg());
105+
if ($this->throwInvalidDirectiveException) {
106+
throw new InvalidArgumentException($message);
107+
}
108+
$this->logger->critical($message);
109+
continue;
110+
}
111+
if ($result === 1) {
91112
return $this->policyFactory->create(
92113
$this->nonce,
93114
$this->configuration['backend'],

Tests/Unit/Http/CspHeaderMiddlewareTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Psr\Http\Message\ServerRequestInterface;
1818
use Psr\Http\Message\UriInterface;
1919
use Psr\Http\Server\RequestHandlerInterface;
20+
use Psr\Log\LoggerInterface;
2021
use ReflectionClass;
2122
use Throwable;
2223

@@ -34,6 +35,7 @@ class CspHeaderMiddlewareTest extends TestCase
3435
private readonly UriInterface&MockObject $uriMock;
3536
private readonly PolicyFactory&MockObject $policyFactoryMock;
3637
private readonly Policy&MockObject $policyMock;
38+
private readonly LoggerInterface&MockObject $loggerMock;
3739

3840
/**
3941
* @throws Throwable
@@ -51,6 +53,7 @@ protected function setUp(): void
5153
$this->uriMock = $this->createMock(UriInterface::class);
5254
$this->policyFactoryMock = $this->createMock(PolicyFactory::class);
5355
$this->policyMock = $this->createMock(Policy::class);
56+
$this->loggerMock = $this->createMock(LoggerInterface::class);
5457

5558
$this->middlewareReflection = new ReflectionClass($this->middleware);
5659

@@ -75,6 +78,12 @@ protected function setUp(): void
7578
['backend' => ['matchUris' => ['^/neos']], 'custom-backend' => ['matchUris' => []]]
7679
);
7780

81+
$reflectionProperty = $this->middlewareReflection->getProperty('throwInvalidDirectiveException');
82+
$reflectionProperty->setValue($this->middleware, true);
83+
84+
$reflectionProperty = $this->middlewareReflection->getProperty('logger');
85+
$reflectionProperty->setValue($this->middleware, $this->loggerMock);
86+
7887
$this->requestHandlerMock->expects($this->once())->method('handle')->willReturn($this->responseMock);
7988
}
8089

@@ -166,4 +175,42 @@ public function testProcessShouldNotMatchNeosWhenBackendMatchUrisOverridden(): v
166175

167176
$this->middleware->process($this->requestMock, $this->requestHandlerMock);
168177
}
178+
179+
public function testProcessThrowsOnInvalidMatchUriPattern(): void
180+
{
181+
$reflectionProperty = $this->middlewareReflection->getProperty('policies');
182+
$reflectionProperty->setValue(
183+
$this->middleware,
184+
['backend' => ['matchUris' => ['^/neos(']], 'custom-backend' => ['matchUris' => []]]
185+
);
186+
187+
$this->requestMock->expects($this->once())->method('getUri')->willReturn($this->uriMock);
188+
$this->uriMock->expects($this->once())->method('getPath')->willReturn('/neos');
189+
190+
$this->expectException(\InvalidArgumentException::class);
191+
192+
$this->middleware->process($this->requestMock, $this->requestHandlerMock);
193+
}
194+
195+
public function testProcessLogsInvalidMatchUriPatternInProduction(): void
196+
{
197+
$reflectionProperty = $this->middlewareReflection->getProperty('throwInvalidDirectiveException');
198+
$reflectionProperty->setValue($this->middleware, false);
199+
200+
$reflectionProperty = $this->middlewareReflection->getProperty('policies');
201+
$reflectionProperty->setValue(
202+
$this->middleware,
203+
['backend' => ['matchUris' => ['^/neos(']], 'custom-backend' => ['matchUris' => []]]
204+
);
205+
206+
$this->requestMock->expects($this->once())->method('getUri')->willReturn($this->uriMock);
207+
$this->uriMock->expects($this->once())->method('getPath')->willReturn('/neos');
208+
209+
$this->loggerMock->expects($this->once())->method('critical');
210+
$this->policyFactoryMock->expects($this->once())->method('create')->willReturn($this->policyMock);
211+
$this->policyMock->expects($this->once())->method('hasNonceDirectiveValue')->willReturn(false);
212+
$this->responseMock->expects($this->once())->method('withAddedHeader')->willReturnSelf();
213+
214+
$this->middleware->process($this->requestMock, $this->requestHandlerMock);
215+
}
169216
}

0 commit comments

Comments
 (0)