From 0412e910605dce0653d3368cfe7809b6d9579d72 Mon Sep 17 00:00:00 2001 From: Zmey Date: Thu, 10 Sep 2020 23:01:01 +0300 Subject: [PATCH] [SecurityBundle] Comma separated ips for security.access_control --- .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../app/StandardFormLogin/config.yml | 3 ++ .../Component/HttpFoundation/CHANGELOG.md | 3 +- .../HttpFoundation/RequestMatcher.php | 6 +++- .../Tests/RequestMatcherTest.php | 34 +++++++++++++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 818aadecf3..2fe6c20335 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Added `FirewallListenerFactoryInterface`, which can be implemented by security factories to add firewall listeners * Added `SortFirewallListenersPass` to make the execution order of firewall listeners configurable by leveraging `Symfony\Component\Security\Http\Firewall\FirewallListenerInterface` + * Added ability to use comma separated ip address list for `security.access_control` 5.1.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml index 328242d279..b35ad3f4c9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml @@ -3,6 +3,7 @@ imports: parameters: env(APP_IP): '127.0.0.1' + env(APP_IPS): '127.0.0.1, ::1' security: encoders: @@ -47,7 +48,9 @@ security: - { path: ^/secured-by-one-real-ip-with-mask$, ips: '203.0.113.0/24', roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/secured-by-one-real-ipv6$, ips: 0:0:0:0:0:ffff:c633:6400, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/secured-by-one-env-placeholder$, ips: '%env(APP_IP)%', roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/secured-by-one-env-placeholder-multiple-ips$, ips: '%env(APP_IPS)%', roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/secured-by-one-env-placeholder-and-one-real-ip$, ips: ['%env(APP_IP)%', 198.51.100.0], roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/secured-by-one-env-placeholder-multiple-ips-and-one-real-ip$, ips: ['%env(APP_IPS)%', 198.51.100.0], roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/highly_protected_resource$, roles: IS_ADMIN } - { path: ^/protected-via-expression$, allow_if: "(is_anonymous() and request.headers.get('user-agent') matches '/Firefox/i') or is_granted('ROLE_USER')" } - { path: .*, roles: IS_AUTHENTICATED_FULLY } diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 85868b22a7..babb87c2b7 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -4,9 +4,10 @@ CHANGELOG 5.2.0 ----- -* added support for `X-Forwarded-Prefix` header + * added support for `X-Forwarded-Prefix` header * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names * added `File::getContent()` + * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` 5.1.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/RequestMatcher.php b/src/Symfony/Component/HttpFoundation/RequestMatcher.php index c32c5cdce5..ab778ea585 100644 --- a/src/Symfony/Component/HttpFoundation/RequestMatcher.php +++ b/src/Symfony/Component/HttpFoundation/RequestMatcher.php @@ -125,7 +125,11 @@ class RequestMatcher implements RequestMatcherInterface */ public function matchIps($ips) { - $this->ips = null !== $ips ? (array) $ips : []; + $ips = null !== $ips ? (array) $ips : []; + + $this->ips = array_reduce($ips, static function (array $ips, string $ip) { + return array_merge($ips, preg_split('/\s*,\s*/', $ip)); + }, []); } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php index 57e9c3d30f..6fab4e712c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestMatcherTest.php @@ -163,4 +163,38 @@ class RequestMatcherTest extends TestCase $matcher->matchAttribute('foo', 'babar'); $this->assertFalse($matcher->matches($request)); } + + public function testIps() + { + $matcher = new RequestMatcher(); + + $request = Request::create('', 'GET', [], [], [], ['REMOTE_ADDR' => '127.0.0.1']); + + $matcher->matchIp('127.0.0.1'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchIp('192.168.0.1'); + $this->assertFalse($matcher->matches($request)); + + $matcher->matchIps('127.0.0.1'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchIps('127.0.0.1, ::1'); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchIps('192.168.0.1, ::1'); + $this->assertFalse($matcher->matches($request)); + + $matcher->matchIps(['127.0.0.1', '::1']); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchIps(['192.168.0.1', '::1']); + $this->assertFalse($matcher->matches($request)); + + $matcher->matchIps(['1.1.1.1', '2.2.2.2', '127.0.0.1, ::1']); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchIps(['1.1.1.1', '2.2.2.2', '192.168.0.1, ::1']); + $this->assertFalse($matcher->matches($request)); + } }