From cb8e4b2f184c240f1d5a90b129e2b0a8d54d9617 Mon Sep 17 00:00:00 2001 From: Vidar Langseid Date: Wed, 14 Jan 2026 13:38:57 +0100 Subject: [PATCH 1/3] IBX-11181: Trusted Proxies is not set on Ibexa Cloud --- .../TrustedHeaderClientIpEventSubscriber.php | 33 ++----------------- src/bundle/Core/Resources/config/services.yml | 2 -- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php index cff112d523..857f3226b6 100644 --- a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php +++ b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php @@ -15,16 +15,6 @@ final class TrustedHeaderClientIpEventSubscriber implements EventSubscriberInterface { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - - private ?string $trustedHeaderName; - - public function __construct( - ?string $trustedHeaderName - ) { - $this->trustedHeaderName = $trustedHeaderName; - } - public static function getSubscribedEvents(): array { return [ @@ -36,28 +26,9 @@ public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); - $trustedProxies = Request::getTrustedProxies(); - $trustedHeaderSet = Request::getTrustedHeaderSet(); - - $trustedHeaderName = $this->trustedHeaderName; - if (null === $trustedHeaderName && $this->isPlatformShProxy($request)) { - $trustedHeaderName = self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP; + if ($this->isPlatformShProxy($request) && $request->headers->get('Client-Cdn') === 'fastly') { + Request::setTrustedProxies(['REMOTE_ADDR'], Request::getTrustedHeaderSet()); } - - if (null === $trustedHeaderName) { - return; - } - - $trustedClientIp = $request->headers->get($trustedHeaderName); - - if (null !== $trustedClientIp) { - if ($trustedHeaderSet !== -1) { - $trustedHeaderSet |= Request::HEADER_X_FORWARDED_FOR; - } - $request->headers->set('X_FORWARDED_FOR', $trustedClientIp); - } - - Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); } private function isPlatformShProxy(Request $request): bool diff --git a/src/bundle/Core/Resources/config/services.yml b/src/bundle/Core/Resources/config/services.yml index c0c93103cb..4e37a774d4 100644 --- a/src/bundle/Core/Resources/config/services.yml +++ b/src/bundle/Core/Resources/config/services.yml @@ -312,8 +312,6 @@ services: $cache: '@ibexa.cache_pool' Ibexa\Bundle\Core\EventSubscriber\TrustedHeaderClientIpEventSubscriber: - arguments: - $trustedHeaderName: '%ibexa.trusted_header_client_ip_name%' tags: - {name: kernel.event_subscriber} From d53633caf4f428b803e553b5ef43bd4706664af4 Mon Sep 17 00:00:00 2001 From: Vidar Langseid Date: Mon, 19 Jan 2026 14:25:35 +0100 Subject: [PATCH 2/3] Fixed tests --- ...ustedHeaderClientIpEventSubscriberTest.php | 111 +++--------------- 1 file changed, 19 insertions(+), 92 deletions(-) diff --git a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php index 55446a653d..14299a8c23 100644 --- a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php +++ b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php @@ -19,16 +19,10 @@ final class TrustedHeaderClientIpEventSubscriberTest extends TestCase { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - private ?string $originalRemoteAddr; - private const PROXY_IP = '127.100.100.1'; - private const REAL_CLIENT_IP = '98.76.123.234'; - private const CUSTOM_CLIENT_IP = '234.123.78.98'; - /** * @param array $data */ @@ -53,114 +47,47 @@ protected function tearDown(): void public function getTrustedHeaderEventSubscriberTestData(): array { return [ - 'default behaviour' => [ - self::REAL_CLIENT_IP, - self::REAL_CLIENT_IP, - ], - 'use custom header name with valid value' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - 'X-Custom-Header', - ['X-Custom-Header' => self::REAL_CLIENT_IP], + 'request from random client received on non-Upsun platform' => [ + false, + [], + [], ], - 'use custom header name without valid value' => [ - self::PROXY_IP, - self::PROXY_IP, - 'X-Custom-Header', + 'request from random client, forging Client-Cdn received on non-Upsun platform' => [ + false, + ['Client-Cdn' => 'fastly'], + [], ], - 'use custom header value without custom header name' => [ - self::PROXY_IP, - self::PROXY_IP, - null, - ['X-Custom-Header' => self::REAL_CLIENT_IP], - ], - 'default platform.sh behaviour' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - ['X-Client-IP' => self::REAL_CLIENT_IP], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use custom header name without valid value on platform.sh' => [ - self::PROXY_IP, - self::PROXY_IP, - 'X-Custom-Header', - [self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP], + 'request from random client received on Upsun platform' => [ + false, + [], ['PLATFORM_RELATIONSHIPS' => true], ], - 'use custom header with valid value on platform.sh' => [ - self::CUSTOM_CLIENT_IP, - self::PROXY_IP, - 'X-Custom-Header', - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use valid value without custom header name on platform.sh' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], + 'request via Fastly received on Upsun platform' => [ + true, + ['Client-Cdn' => 'fastly'], ['PLATFORM_RELATIONSHIPS' => true], ], ]; } - public function testTrustedHeaderEventSubscriberWithoutTrustedProxy(): void - { - $_SERVER['REMOTE_ADDR'] = self::PROXY_IP; - - $eventDispatcher = new EventDispatcher(); - $eventDispatcher->addSubscriber( - new TrustedHeaderClientIpEventSubscriber('X-Custom-Header') - ); - - $request = Request::create('/', 'GET', [], [], [], array_merge( - $_SERVER, - ['PLATFORM_RELATIONSHIPS' => true], - )); - $request->headers->add([ - 'X-Custom-Header' => self::REAL_CLIENT_IP, - ]); - - $event = $eventDispatcher->dispatch(new RequestEvent( - self::createMock(KernelInterface::class), - $request, - HttpKernelInterface::MAIN_REQUEST - ), KernelEvents::REQUEST); - - /** @var \Symfony\Component\HttpFoundation\Request $request */ - $request = $event->getRequest(); - - self::assertEquals(self::PROXY_IP, $request->getClientIp()); - } - /** * @dataProvider getTrustedHeaderEventSubscriberTestData */ public function testTrustedHeaderEventSubscriberWithTrustedProxy( - string $expectedIp, - string $remoteAddrIp, - ?string $trustedHeaderName = null, + bool $isFromTrustedProxy, array $headers = [], array $server = [] ): void { - $_SERVER['REMOTE_ADDR'] = $remoteAddrIp; - Request::setTrustedProxies(['REMOTE_ADDR'], Request::getTrustedHeaderSet()); + $_SERVER['REMOTE_ADDR'] = self::REAL_CLIENT_IP; $eventDispatcher = new EventDispatcher(); $eventDispatcher->addSubscriber( - new TrustedHeaderClientIpEventSubscriber($trustedHeaderName) + new TrustedHeaderClientIpEventSubscriber() ); $request = Request::create('/', 'GET', [], [], [], array_merge( $server, - ['REMOTE_ADDR' => $remoteAddrIp], + ['REMOTE_ADDR' => self::REAL_CLIENT_IP], )); $request->headers->add($headers); @@ -173,6 +100,6 @@ public function testTrustedHeaderEventSubscriberWithTrustedProxy( /** @var \Symfony\Component\HttpFoundation\Request $request */ $request = $event->getRequest(); - self::assertEquals($expectedIp, $request->getClientIp()); + self::assertEquals($isFromTrustedProxy, $request->isFromTrustedProxy()); } } From 8e6ec00037bc27d3ec78b640ee19573d9c4ff777 Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Thu, 30 Jul 2026 12:52:28 +0200 Subject: [PATCH 3/3] IBX-11181: PHPStan --- phpstan-baseline.neon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 15cd76ff78..fbfa0a2475 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -41122,7 +41122,7 @@ parameters: - message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Location'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Location will always evaluate to true\.$#' identifier: method.alreadyNarrowedType - count: 10 + count: 9 path: tests/integration/Core/Repository/LocationServiceTest.php - @@ -41152,7 +41152,7 @@ parameters: - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Location'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Content\\Location will always evaluate to true\.$#' identifier: staticMethod.alreadyNarrowedType - count: 2 + count: 1 path: tests/integration/Core/Repository/LocationServiceTest.php -