Skip to content

[SecurityBundle] Add a FirewallConfigRegistry service as main entry point #20591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

[SecurityBundle] Add a FirewallConfigRegistry service as main entry point #20591

wants to merge 1 commit into from

Conversation

ogizanagi
Copy link
Contributor

@ogizanagi ogizanagi commented Nov 22, 2016

Q A
Branch? 3.2
Bug fix? no
New feature? yes (but rework a new 3.2 feature)
BC breaks? no
Deprecations? no (removes one)
Tests pass? yes
Fixed tickets 20585#issuecomment-262085751
License MIT
Doc PR N/A

This PR reworks some parts of #19398 for solving issues like #20585 about accessing the firewall configs in different ways.
The main entry point for getting firewall configs becomes the security.firewall.config_registry service.
FirewallMap & FirewallContext stay unchanged, as they are more about the security execution context than getting the configuration.

It also removes the deprecation introduced in FirewallContext (and even in case this one is not merged, I'd like to challenge this deprecation which seems superfluous instead of simply allowing null)

However, if the only real uses-cases are only to access the config at runtime from the firewall name, we may not need that "complexity" and refactoring (see #20592 instead).

WDYT?

cc @chalasr

*/
private function getRequestMatcher(FirewallConfig $config)
{
if (empty($config->getRequestMatcher())) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this would be replaced by if (null === $config->getRequestMatcher()) { if #20589 is merged

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of this one is considered before #20589, I think it should be if (!$config->getRequestMatcher())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer empty which is semantically better IMHO.

@chalasr
Copy link
Member

chalasr commented Nov 22, 2016

Imho, adding this registry makes sense as soon as (and only if) we need some more accessors for the FirewallConfig.

The current() method makes sense, but you can get the same result with the current implementation using FirewallMap::getFirewallConfig($requestStack->getCurrentRequest()) which is exactly what the fromRequest() method added here does, and I do think using FirewallMap is good enough for that.

Given I can't find valid use cases forall() and inContext() (maybe I missed one?) and the need reported in #20585 (corresponding to get() added here) can be easily solved by #20592 instead (making the service public), I would say we don't need such a service right now.

Of course that's just my opinion and I may be wrong but I would favor #20592 instead of this one, even if your implementation looks very good.

edit: considering the use cases, maybe it's worth it.

@ogizanagi
Copy link
Contributor Author

ogizanagi commented Nov 22, 2016

inContext() was motivated by the need to identify firewalls sharing a same context in #20516, but we've injected the context along with the logout listener informations instead.

all() may be used to collect informations about the application, to complete the profiler for instance (firewalls order, request matching informations, ...).

Despite I prefer having this clear entrypoint separated from the security execution context, I do think identifying proper use cases to legitimate this approach is required. Maybe @julienfalque could give us some hints?

}
}

return $configs;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

- $configs = array();
- foreach ($this->firewallConfigs as $config) {
-     if ($config->getContext() === $context) {
-         $configs[] = $config;
-     }
- }
-
- return $configs;
+ return array_filter($this->firewallConfigs, function (FirewallConfig $config) {
+     return $context === config->getContext();
+ });

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure 👍

*/
private function getRequestMatcher(FirewallConfig $config)
{
if (empty($config->getRequestMatcher())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of this one is considered before #20589, I think it should be if (!$config->getRequestMatcher())

@julienfalque
Copy link
Contributor

I need to be able to retrieve a FirewallConfig by name for #20426. This would allow me to retrieve the config of a Firewall and use matching field names (actually with more work to retrieve firewall options, but this will probably be another PR).

Making the FirewallConfig public could be a solution but, as I will know the firewall name at runtime (form type option), it would require to either inject the container or all the FirewallConfig instances using tags. I think this dedicated FirewallConfigRegistry service is an easier and more elegant solution.

@nicolas-grekas
Copy link
Member

This one is way too late in the 3.2 release cycle IMHO. Is it superseded by #20592?

@ogizanagi
Copy link
Contributor Author

ogizanagi commented Nov 23, 2016

Of course I suspected this. The time left before releasing 3.2 is probably too short for such a change, but If we want to do it later, we fall in the deprecation cycle. So I had to at least try.

#20592 would be enough for use-cases I can imagine right now. But as you said, this is actually solvable by defining aliases on userland.

@nicolas-grekas
Copy link
Member

So maybe close this one until someone comes with a use case?

@chalasr
Copy link
Member

chalasr commented Nov 23, 2016

@nicolas-grekas Apparently there is one use case at least (#20591 (comment)) for retrieving firewall config by name at runtime without having the whole container injected, so maybe this one is good to keep on 3.3.

Another alternative could be to add the logic needed by #20591 (comment) in the FirewallMap, like FirewallMap::getFirewallConfig($name); which makes sense imho, but it would be for 3.3 anyway.

@ogizanagi
Copy link
Contributor Author

As a side note: WDYT about removing the deprecation in FirewallContext ?

Having the configuration object on the FirewallContext is a bonus and isn't required for the security flow to work.
If this PR is legitimated for 3.3, we'll deprecate this argument from the constructor anyway in order to remove it in 4.0.

@chalasr
Copy link
Member

chalasr commented Nov 23, 2016

👍 for removing the deprecation on 3.2.

@nicolas-grekas
Copy link
Member

@ogizanagi can you update #20589 to remove the deprecation?

@ogizanagi
Copy link
Contributor Author

Done. Closing this one for now.

@ogizanagi ogizanagi closed this Nov 23, 2016
@ogizanagi ogizanagi deleted the firewall_config_registry branch November 23, 2016 14:39
@julienfalque
Copy link
Contributor

So... Is this totally abandoned or do we still want it on 3.3? I don't think using public aliases will help for the use case I mentioned.

@ogizanagi
Copy link
Contributor Author

@julienfalque : We must have enough arguments for this to happen in 3.3, because it'll require extra work to deprecate paths introduced in 3.2 and ensuring BC until 4.0. That's why I thought we may rework it before it's too late and 3.2 is released...but it's already too late 😅

Note that #20585 may still happen in 3.3 as is if we don't mind mixing responsibilities between the security flow and getting the config objects.

fabpot added a commit that referenced this pull request Nov 24, 2016
…izanagi)

This PR was squashed before being merged into the 3.2 branch (closes #20589).

Discussion
----------

[SecurityBundle] Fix FirewallConfig nullable arguments

| Q             | A
| ------------- | ---
| Branch?       | 3.2
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no, but removes one
| Tests pass?   | yes
| Fixed tickets | N/A
| License       | MIT
| Doc PR        | N/A

Nullable arguments were replaced by empty strings by the DIC config if values weren't replaced in the extension.

Another solution (looking safer to me) is to apply the following changes in the DIC configuration:

```diff
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index 54e5734..499dd5e 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -116,15 +116,15 @@

         <service id="security.firewall.config" class="Symfony\Bundle\SecurityBundle\Security\FirewallConfig" abstract="true" public="false">
             <argument />                   <!-- name -->
-            <argument />                   <!-- user_checker -->
-            <argument />                   <!-- request_matcher -->
-            <argument />                   <!-- security enabled -->
-            <argument />                   <!-- stateless -->
-            <argument />                   <!-- provider -->
-            <argument />                   <!-- context -->
-            <argument />                   <!-- entry_point -->
-            <argument />                   <!-- access_denied_handler -->
-            <argument />                   <!-- access_denied_url -->
+            <argument>null</argument>      <!-- user_checker -->
+            <argument>null</argument>      <!-- request_matcher -->
+            <argument>true</argument>      <!-- security enabled -->
+            <argument>false</argument>     <!-- stateless -->
+            <argument>null</argument>      <!-- provider -->
+            <argument>null</argument>      <!-- context -->
+            <argument>null</argument>      <!-- entry_point -->
+            <argument>null</argument>      <!-- access_denied_handler -->
+            <argument>null</argument>      <!-- access_denied_url -->
             <argument type="collection" /> <!-- listeners -->
         </service>
```

But it doesn't seem to be the way we deal with arguments meant to be replaced by extensions in the Symfony core.

cc @chalasr

This PR also removes the FirewallContext mandatory `FirewallConfig` argument deprecation for reasons expressed in #20591 (comment)

Commits
-------

79ef474 [SecurityBundle] Remove FirewallContext mandatory FirewallConfig argument deprecation
f09ccf4 [SecurityBundle] Fix FirewallConfig nullable arguments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants