[SecurityBundle] [HttpFoundation] Allow for multiple IP address in security access_control rules
This commit is contained in:
parent
54b32f1a4a
commit
650352d1ca
@ -152,6 +152,7 @@ class MainConfiguration implements ConfigurationInterface
|
||||
->arrayNode('access_control')
|
||||
->cannotBeOverwritten()
|
||||
->prototype('array')
|
||||
->fixXmlConfig('ip')
|
||||
->children()
|
||||
->scalarNode('requires_channel')->defaultNull()->end()
|
||||
->scalarNode('path')
|
||||
@ -160,7 +161,10 @@ class MainConfiguration implements ConfigurationInterface
|
||||
->example('^/path to resource/')
|
||||
->end()
|
||||
->scalarNode('host')->defaultNull()->end()
|
||||
->scalarNode('ip')->defaultNull()->end()
|
||||
->arrayNode('ips')
|
||||
->beforeNormalization()->ifString()->then(function($v) { return array($v); })->end()
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->arrayNode('methods')
|
||||
->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end()
|
||||
->prototype('scalar')->end()
|
||||
|
@ -184,7 +184,7 @@ class SecurityExtension extends Extension
|
||||
$access['path'],
|
||||
$access['host'],
|
||||
$access['methods'],
|
||||
$access['ip']
|
||||
$access['ips']
|
||||
);
|
||||
|
||||
$container->getDefinition('security.access_map')
|
||||
|
@ -25,6 +25,12 @@ form_login_redirect_to_protected_resource_after_login:
|
||||
highly_protected_resource:
|
||||
path: /highly_protected_resource
|
||||
|
||||
secured-by-one-ip:
|
||||
path: /secured-by-one-ip
|
||||
|
||||
secured-by-two-ips:
|
||||
path: /secured-by-two-ips
|
||||
|
||||
form_logout:
|
||||
path: /logout_path
|
||||
|
||||
|
@ -63,6 +63,44 @@ class SecurityRoutingIntegrationTest extends WebTestCase
|
||||
$this->assertNotEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getConfigs
|
||||
* @group ip_whitelist
|
||||
*/
|
||||
public function testSecurityConfigurationForSingleIPAddress($config)
|
||||
{
|
||||
$allowedClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array("REMOTE_ADDR" => "10.10.10.10"));
|
||||
$barredClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array("REMOTE_ADDR" => "10.10.20.10"));
|
||||
|
||||
$this->assertAllowed($allowedClient, '/secured-by-one-ip');
|
||||
$this->assertRestricted($barredClient, '/secured-by-one-ip');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getConfigs
|
||||
* @group ip_whitelist
|
||||
*/
|
||||
public function testSecurityConfigurationForMultipleIPAddresses($config)
|
||||
{
|
||||
$allowedClientA = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array("REMOTE_ADDR" => "1.1.1.1"));
|
||||
$allowedClientB = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array("REMOTE_ADDR" => "2.2.2.2"));
|
||||
$barredClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array("REMOTE_ADDR" => "192.168.1.1"));
|
||||
|
||||
$this->assertAllowed($allowedClientA, '/secured-by-two-ips');
|
||||
$this->assertAllowed($allowedClientB, '/secured-by-two-ips');
|
||||
$this->assertRestricted($barredClient, '/secured-by-two-ips');
|
||||
}
|
||||
|
||||
private function assertAllowed($client, $path) {
|
||||
$client->request('GET', $path);
|
||||
$this->assertEquals(404, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
private function assertRestricted($client, $path) {
|
||||
$client->request('GET', $path);
|
||||
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function getConfigs()
|
||||
{
|
||||
return array(array('config.yml'), array('routes_as_path.yml'));
|
||||
|
@ -28,5 +28,7 @@ security:
|
||||
access_control:
|
||||
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/secured-by-one-ip$, ip: 10.10.10.10, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/secured-by-two-ips$, ips: [1.1.1.1, 2.2.2.2], roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/highly_protected_resource$, roles: IS_ADMIN }
|
||||
- { path: .*, roles: IS_AUTHENTICATED_FULLY }
|
||||
|
@ -38,7 +38,7 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $ip;
|
||||
private $ips = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@ -49,15 +49,15 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
* @param string|null $path
|
||||
* @param string|null $host
|
||||
* @param string|string[]|null $methods
|
||||
* @param string|null $ip
|
||||
* @param string|string[]|null $ips
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($path = null, $host = null, $methods = null, $ip = null, array $attributes = array())
|
||||
public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array())
|
||||
{
|
||||
$this->matchPath($path);
|
||||
$this->matchHost($host);
|
||||
$this->matchMethod($methods);
|
||||
$this->matchIp($ip);
|
||||
$this->matchIps($ips);
|
||||
foreach ($attributes as $k => $v) {
|
||||
$this->matchAttribute($k, $v);
|
||||
}
|
||||
@ -90,7 +90,17 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
*/
|
||||
public function matchIp($ip)
|
||||
{
|
||||
$this->ip = $ip;
|
||||
$this->matchIps($ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a check for the client IP.
|
||||
*
|
||||
* @param string|string[] $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24
|
||||
*/
|
||||
public function matchIps($ips)
|
||||
{
|
||||
$this->ips = (array) $ips;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,10 +153,15 @@ class RequestMatcher implements RequestMatcherInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $this->ip && !IpUtils::checkIp($request->getClientIp(), $this->ip)) {
|
||||
return false;
|
||||
foreach($this->ips as $ip) {
|
||||
if (IpUtils::checkIp($request->getClientIp(), $ip)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// Note to future implementors: add additional checks above the
|
||||
// foreach above or else your check might not be run!
|
||||
|
||||
return count($this->ips) === 0;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user