Skip to content

Commit aa59a52

Browse files
committed
feature #37357 [FrameworkBundle] allow configuring trusted proxies using semantic configuration (nicolas-grekas)
This PR was merged into the 5.2-dev branch. Discussion ---------- [FrameworkBundle] allow configuring trusted proxies using semantic configuration | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | - | Tickets | - | License | MIT | Doc PR | - On top of the improved DX this should provide, this PR (and #37351) will allow [removing the corresponding lines](symfony/recipes#790) from `index.php` & recipes. Using values: ```yaml framework: trusted_proxies: '127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16' #or trusted_proxies: '%env(TRUSTED_PROXIES)%' ``` `trusted_headers` is similar but is an array of headers to trust. ```yaml framework: # that's the defaults already trusted_headers: ['x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix'] ``` Commits ------- af9dd52752 [FrameworkBundle] allow configuring trusted proxies using semantic configuration
2 parents 54d786c + 59200cd commit aa59a52

File tree

7 files changed

+59
-11
lines changed

7 files changed

+59
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* Added `framework.http_cache` configuration tree
8+
* Added `framework.trusted_proxies` and `framework.trusted_headers` configuration options
89

910
5.1.0
1011
-----

DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ public function getConfigTreeBuilder()
8585
->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end()
8686
->prototype('scalar')->end()
8787
->end()
88+
->scalarNode('trusted_proxies')->end()
89+
->arrayNode('trusted_headers')
90+
->fixXmlConfig('trusted_header')
91+
->performNoDeepMerging()
92+
->defaultValue(['x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix'])
93+
->beforeNormalization()->ifString()->then(function ($v) { return $v ? array_map('trim', explode(',', $v)) : []; })->end()
94+
->enumPrototype()
95+
->values([
96+
'forwarded',
97+
'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port',
98+
'x-forwarded-all', '!x-forwarded-host', '!x-forwarded-prefix',
99+
])
100+
->end()
101+
->end()
88102
->scalarNode('error_controller')
89103
->defaultValue('error_controller')
90104
->end()

DependencyInjection/FrameworkExtension.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
use Symfony\Component\Form\FormTypeGuesserInterface;
6666
use Symfony\Component\Form\FormTypeInterface;
6767
use Symfony\Component\HttpClient\ScopingHttpClient;
68+
use Symfony\Component\HttpFoundation\Request;
6869
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
6970
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
7071
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
@@ -242,6 +243,11 @@ public function load(array $configs, ContainerBuilder $container)
242243
$container->setParameter('kernel.default_locale', $config['default_locale']);
243244
$container->setParameter('kernel.error_controller', $config['error_controller']);
244245

246+
if (($config['trusted_proxies'] ?? false) && ($config['trusted_headers'] ?? false)) {
247+
$container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
248+
$container->setParameter('kernel.trusted_headers', $this->resolveTrustedHeaders($config['trusted_headers']));
249+
}
250+
245251
if (!$container->hasParameter('debug.file_link_format')) {
246252
$links = [
247253
'textmate' => 'txmt://open?url=file://%%f&line=%%l',
@@ -2094,6 +2100,30 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
20942100
}
20952101
}
20962102

2103+
private function resolveTrustedHeaders(array $headers): int
2104+
{
2105+
$trustedHeaders = 0;
2106+
2107+
foreach ($headers as $h) {
2108+
switch ($h) {
2109+
case 'forwarded': $trustedHeaders |= Request::HEADER_FORWARDED; break;
2110+
case 'x-forwarded-for': $trustedHeaders |= Request::HEADER_X_FORWARDED_FOR; break;
2111+
case 'x-forwarded-host': $trustedHeaders |= Request::HEADER_X_FORWARDED_HOST; break;
2112+
case 'x-forwarded-proto': $trustedHeaders |= Request::HEADER_X_FORWARDED_PROTO; break;
2113+
case 'x-forwarded-port': $trustedHeaders |= Request::HEADER_X_FORWARDED_PORT; break;
2114+
case '!x-forwarded-host': $trustedHeaders &= ~Request::HEADER_X_FORWARDED_HOST; break;
2115+
case 'x-forwarded-all':
2116+
if (!\in_array('!x-forwarded-prefix', $headers)) {
2117+
throw new LogicException('When using "x-forwarded-all" in "framework.trusted_headers", "!x-forwarded-prefix" must be explicitly listed until support for X-Forwarded-Prefix is implemented.');
2118+
}
2119+
$trustedHeaders |= Request::HEADER_X_FORWARDED_ALL;
2120+
break;
2121+
}
2122+
}
2123+
2124+
return $trustedHeaders;
2125+
}
2126+
20972127
/**
20982128
* {@inheritdoc}
20992129
*/

FrameworkBundle.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ public function boot()
9595
if ($this->container->getParameter('kernel.http_method_override')) {
9696
Request::enableHttpMethodParameterOverride();
9797
}
98-
99-
if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) {
100-
Request::setTrustedHosts($trustedHosts);
101-
}
10298
}
10399

104100
public function build(ContainerBuilder $container)

Resources/config/schema/symfony-1.0.xsd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
<xsd:attribute name="default-locale" type="xsd:string" />
4343
<xsd:attribute name="test" type="xsd:boolean" />
4444
<xsd:attribute name="error-controller" type="xsd:string" />
45+
<xsd:attribute name="trusted_hosts" type="xsd:string" />
46+
<xsd:attribute name="trusted_proxies" type="xsd:string" />
47+
<xsd:attribute name="trusted_headers" type="xsd:string" />
4548
</xsd:complexType>
4649

4750
<xsd:complexType name="form">

Resources/config/services.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@
132132
->tag('container.hot_path')
133133

134134
->set('http_cache.store', Store::class)
135-
->args([
136-
param('kernel.cache_dir').'/http_cache',
137-
])
135+
->args([
136+
param('kernel.cache_dir').'/http_cache',
137+
])
138138

139139
->set('url_helper', UrlHelper::class)
140140
->args([

Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ public function testDefaultConfig()
3030
$processor = new Processor();
3131
$config = $processor->processConfiguration(new Configuration(true), [['secret' => 's3cr3t']]);
3232

33-
$this->assertEquals(
34-
array_merge(['secret' => 's3cr3t', 'trusted_hosts' => []], self::getBundleDefaultConfig()),
35-
$config
36-
);
33+
$this->assertEquals(self::getBundleDefaultConfig(), $config);
3734
}
3835

3936
public function getTestValidSessionName()
@@ -341,6 +338,13 @@ protected static function getBundleDefaultConfig()
341338
'http_method_override' => true,
342339
'ide' => null,
343340
'default_locale' => 'en',
341+
'secret' => 's3cr3t',
342+
'trusted_hosts' => [],
343+
'trusted_headers' => [
344+
'x-forwarded-all',
345+
'!x-forwarded-host',
346+
'!x-forwarded-prefix',
347+
],
344348
'csrf_protection' => [
345349
'enabled' => false,
346350
],

0 commit comments

Comments
 (0)