Integrate current firewall in profiler

This commit is contained in:
Robin Chalas 2016-07-30 11:03:31 +02:00
parent 904e90ba63
commit 75e208e419
No known key found for this signature in database
GPG Key ID: 89672113756EE03B
4 changed files with 229 additions and 46 deletions

View File

@ -21,6 +21,8 @@ use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\DebugAccessDecisionManager;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\Security\Http\FirewallMapInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMAp;
/**
* SecurityDataCollector.
@ -33,6 +35,7 @@ class SecurityDataCollector extends DataCollector
private $roleHierarchy;
private $logoutUrlGenerator;
private $accessDecisionManager;
private $firewallMap;
/**
* Constructor.
@ -41,13 +44,15 @@ class SecurityDataCollector extends DataCollector
* @param RoleHierarchyInterface|null $roleHierarchy
* @param LogoutUrlGenerator|null $logoutUrlGenerator
* @param AccessDecisionManagerInterface|null $accessDecisionManager
* @param FirewallMapInterface|null $firewallMap
*/
public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null)
public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null, FirewallMapInterface $firewallMap = null)
{
$this->tokenStorage = $tokenStorage;
$this->roleHierarchy = $roleHierarchy;
$this->logoutUrlGenerator = $logoutUrlGenerator;
$this->accessDecisionManager = $accessDecisionManager;
$this->firewallMap = $firewallMap;
}
/**
@ -132,6 +137,28 @@ class SecurityDataCollector extends DataCollector
$this->data['voter_strategy'] = 'unknown';
$this->data['voters'] = array();
}
// collect firewall context information
$this->data['firewall'] = null;
if ($this->firewallMap instanceof FirewallMap) {
$firewallConfig = $this->firewallMap->getFirewallConfig($request);
if (null !== $firewallConfig) {
$this->data['firewall'] = array(
'name' => $firewallConfig->getName(),
'allows_anonymous' => $firewallConfig->allowsAnonymous(),
'request_matcher' => $firewallConfig->getRequestMatcher(),
'security_enabled' => $firewallConfig->isSecurityEnabled(),
'stateless' => $firewallConfig->isStateless(),
'provider' => $firewallConfig->getProvider(),
'context' => $firewallConfig->getContext(),
'entry_point' => $firewallConfig->getEntryPoint(),
'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(),
'access_denied_url' => $firewallConfig->getAccessDeniedUrl(),
'user_checker' => $firewallConfig->getUserChecker(),
'listeners' => $this->cloneVar($firewallConfig->getListeners()),
);
}
}
}
/**
@ -255,6 +282,16 @@ class SecurityDataCollector extends DataCollector
return $this->data['access_decision_log'];
}
/**
* Returns the configuration of the current firewall context.
*
* @return array
*/
public function getFirewall()
{
return $this->data['firewall'];
}
/**
* {@inheritdoc}
*/

View File

@ -11,6 +11,7 @@
<argument type="service" id="security.role_hierarchy" />
<argument type="service" id="security.logout_url_generator" />
<argument type="service" id="security.access.decision_manager" />
<argument type="service" id="security.firewall.map" />
</service>
</services>
</container>

View File

@ -33,6 +33,12 @@
<span>{{ collector.tokenClass|abbr_class }}</span>
</div>
{% endif %}
{% if collector.firewall %}
<div class="sf-toolbar-info-piece">
<b>Firewall name</b>
<span>{{ collector.firewall.name }}</span>
</div>
{% endif %}
{% if collector.logoutUrl %}
<div class="sf-toolbar-info-piece">
<b>Actions</b>
@ -63,57 +69,127 @@
{% block panel %}
<h2>Security Token</h2>
{% if collector.token %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.user == 'anon.' ? 'Anonymous' : collector.user }}</span>
<span class="label">Username</span>
{% if collector.enabled %}
{% if collector.token %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.user == 'anon.' ? 'Anonymous' : collector.user }}</span>
<span class="label">Username</span>
</div>
<div class="metric">
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Authenticated</span>
</div>
</div>
<div class="metric">
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Authenticated</span>
<table>
<thead>
<tr>
<th scope="col" class="key">Property</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>Roles</th>
<td>
{{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}
{% if not collector.authenticated and collector.roles is empty %}
<p class="help">User is not authenticated probably because they have no roles.</p>
{% endif %}
</td>
</tr>
{% if collector.supportsRoleHierarchy %}
<tr>
<th>Inherited Roles</th>
<td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
</tr>
{% endif %}
{% if collector.token %}
<tr>
<th>Token</th>
<td>{{ profiler_dump(collector.token) }}</td>
</tr>
{% endif %}
</tbody>
</table>
{% elseif collector.enabled %}
<div class="empty">
<p>There is no security token.</p>
</div>
</div>
{% endif %}
<table>
<thead>
<tr>
<th scope="col" class="key">Property</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>Roles</th>
<td>
{{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}
{% if not collector.authenticated and collector.roles is empty %}
<p class="help">User is not authenticated probably because they have no roles.</p>
{% endif %}
</td>
</tr>
<h2>Security Firewall</h2>
{% if collector.supportsRoleHierarchy %}
<tr>
<th>Inherited Roles</th>
<td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
</tr>
{% endif %}
{% if collector.token %}
<tr>
<th>Token</th>
<td>{{ profiler_dump(collector.token) }}</td>
</tr>
{% endif %}
</tbody>
</table>
{% elseif collector.enabled %}
<div class="empty">
<p>There is no security token.</p>
</div>
{% if collector.firewall %}
<div class="metrics">
<div class="metric">
<span class="value">{{ collector.firewall.name }}</span>
<span class="label">Name</span>
</div>
<div class="metric">
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Security enabled</span>
</div>
<div class="metric">
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Stateless</span>
</div>
<div class="metric">
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.allows_anonymous ? 'yes' : 'no') ~ '.svg') }}</span>
<span class="label">Allows anonymous</span>
</div>
</div>
{% if collector.firewall.security_enabled %}
<table>
<thead>
<tr>
<th scope="col" class="key">Key</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>provider</th>
<td>{{ collector.firewall.provider }}</td>
</tr>
<tr>
<th>context</th>
<td>{{ collector.firewall.context }}</td>
</tr>
<tr>
<th>entry_point</th>
<td>{{ collector.firewall.entry_point }}</td>
</tr>
<tr>
<th>user_checker</th>
<td>{{ collector.firewall.user_checker }}</td>
</tr>
<tr>
<th>access_denied_handler</th>
<td>{{ collector.firewall.access_denied_handler }}</td>
</tr>
<tr>
<th>access_denied_url</th>
<td>{{ collector.firewall.access_denied_url }}</td>
</tr>
<tr>
<th>listeners</th>
<td>{{ collector.firewall.listeners is empty ? 'none' : profiler_dump(collector.firewall.listeners, maxDepth=1) }}</td>
</tr>
</tbody>
</table>
{% endif %}
{% elseif collector.enabled %}
<div class="empty">
<p>There is no firewall.</p>
</div>
{% endif %}
{% else %}
<div class="empty">
<p>The security component is disabled.</p>

View File

@ -12,10 +12,13 @@
namespace Symfony\Bundle\SecurityBundle\Tests\DataCollector;
use Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\RoleHierarchy;
use Symfony\Component\Security\Http\FirewallMapInterface;
class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
{
@ -32,6 +35,7 @@ class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
$this->assertCount(0, $collector->getRoles());
$this->assertCount(0, $collector->getInheritedRoles());
$this->assertEmpty($collector->getUser());
$this->assertNull($collector->getFirewall());
}
public function testCollectWhenAuthenticationTokenIsNull()
@ -47,6 +51,7 @@ class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
$this->assertCount(0, $collector->getRoles());
$this->assertCount(0, $collector->getInheritedRoles());
$this->assertEmpty($collector->getUser());
$this->assertNull($collector->getFirewall());
}
/** @dataProvider provideRoles */
@ -71,6 +76,70 @@ class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
$this->assertSame('hhamon', $collector->getUser());
}
public function testGetFirewall()
{
$firewallConfig = new FirewallConfig('dummy', 'security.request_matcher.dummy');
$request = $this->getRequest();
$firewallMap = $this
->getMockBuilder(FirewallMap::class)
->disableOriginalConstructor()
->getMock();
$firewallMap
->expects($this->once())
->method('getFirewallConfig')
->with($request)
->willReturn($firewallConfig);
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
$collector->collect($request, $this->getResponse());
$collected = $collector->getFirewall();
$this->assertSame($firewallConfig->getName(), $collected['name']);
$this->assertSame($firewallConfig->allowsAnonymous(), $collected['allows_anonymous']);
$this->assertSame($firewallConfig->getRequestMatcher(), $collected['request_matcher']);
$this->assertSame($firewallConfig->isSecurityEnabled(), $collected['security_enabled']);
$this->assertSame($firewallConfig->isStateless(), $collected['stateless']);
$this->assertSame($firewallConfig->getProvider(), $collected['provider']);
$this->assertSame($firewallConfig->getContext(), $collected['context']);
$this->assertSame($firewallConfig->getEntryPoint(), $collected['entry_point']);
$this->assertSame($firewallConfig->getAccessDeniedHandler(), $collected['access_denied_handler']);
$this->assertSame($firewallConfig->getAccessDeniedUrl(), $collected['access_denied_url']);
$this->assertSame($firewallConfig->getUserChecker(), $collected['user_checker']);
$this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getRawData()[0][0]);
}
public function testGetFirewallReturnsNull()
{
$request = $this->getRequest();
$response = $this->getResponse();
// Don't inject any firewall map
$collector = new SecurityDataCollector();
$collector->collect($request, $response);
$this->assertNull($collector->getFirewall());
// Inject an instance that is not context aware
$firewallMap = $this
->getMockBuilder(FirewallMapInterface::class)
->disableOriginalConstructor()
->getMock();
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
$collector->collect($request, $response);
$this->assertNull($collector->getFirewall());
// Null config
$firewallMap = $this
->getMockBuilder(FirewallMap::class)
->disableOriginalConstructor()
->getMock();
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
$collector->collect($request, $response);
$this->assertNull($collector->getFirewall());
}
public function provideRoles()
{
return array(