-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[SecurityBundle] support custom functions inside allow_if expressions #26263
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
Conversation
Should this really be done as a bug fix? Can't we consider it's a limitation for sure, but that's how it works for now? If you agree, then the cache warmup should be added in the PR on master. |
We can also consider it as a undocumented limitation and I can add it as a feature to master. I just find the current behavior kind of weird to be honest. But I don't really mind 😊 Should we use |
a dedicated pool instead, so userland items cannot collide with internals - see eg |
An option for 2.7 could be to keep trying to parse in the extension at compile time, but fallback to runtime parsing (using Expression instead of SerializedParsedExpression) in case of an invalid function being used (as this is the only kind of parse error which can change once registering custom functions). This way, only projects using a custom function in their |
@@ -36,10 +36,10 @@ public function process(ContainerBuilder $container) | |||
} | |||
|
|||
// security | |||
if ($container->has('security.access.expression_voter')) { | |||
$definition = $container->findDefinition('security.access.expression_voter'); | |||
if ($container->has('security.expression_language')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why changing the registration logic ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, registering providers on the right service rather than relying on delegation still makes sense though, to ensure that the security.expression_language
service is usable even if it is instantiated earlier than the ExpressionVoter due to injecting it elsewhere and due to voters being lazy-loaded).
We should probably even deprecated \Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter::addExpressionLanguageProvider
in master as it only delegates the call and the ExpressionLanguage instance is always injected from the outside.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding it to security.expression_language
directly makes more sense? Not even sure why ExpressionVoter::addExpressionLanguageProvider
exists. Maybe I'm missing something?
If someone injects security.expression_language
and uses it without the ExpressionVoter
service ever being instantiated then the custom providers would be missing?
But if it makes merging etc harder I can also revert it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stof exactly 😊
👍 for deprecating it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this change required for 2.7? if not, better revert, isn't it, and do it on master only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No its not required 👍 will revert and apply to master together with the deprecation then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas removed 😉
@stof yes I was also thinking about that. We could catch |
69f6e3c
to
537222f
Compare
@stof @nicolas-grekas I updated it so we keep trying to parse the expression on compile time and we simply fallback to using a raw expression if it fails. Let me know what you think 😉 I could create a separate PR for master to use a new cache pool + deprecate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if the runtime error is an acceptable DX downgrade (vs the current compile time failure)
WDYT?
Hmm not sure its a big problem. I mean when using the FrameworkExtraBundle What do you think @stof ? |
@nicolas-grekas @stof should I continue to work on this? Or should we close the issue as "won't fix"? |
@dmaicher move as new feature on master? |
@nicolas-grekas ok 😉 Will prepare a new PR soon for master that
|
…low_if expressions (dmaicher) This PR was merged into the 4.1-dev branch. Discussion ---------- [SecurityBundle] allow using custom function inside allow_if expressions | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | no | Fixed tickets | #23208 | License | MIT | Doc PR | symfony/symfony-docs#9552 This is a follow-up for #26263 As discussed there I propose to allow using custom functions as a new feature only and thus targeting `master` here. If we agree to move forward with this there are some todos: - [x] fix tests - [x] add cache warmer for allow_if expressions - [x] update documentation to mention this new feature - [x] update UPGRADE files ping @nicolas-grekas @stof Commits ------- 41552cd [SecurityBundle] allow using custom function inside allow_if expressions
This is a follow up for #24309.
Problem:
The
SecurityExtension
was instantiating an\Symfony\Component\Security\Core\Authorization\ExpressionLanguage
instance to parse the expressions defined in the access control config viaallow_if: "..."
. So it used a pre-parsedSerializedParsedExpression
instead of a rawExpression
probably for performance reasons.This has the serious drawback (and that's the bug) that it does not use the service
'security.expression_language'
for this during the compiler pass. So any customizations for the service (like custom providers with functions) are completely ignored here on compile time.Proposed fix
I propose to not dump parsed expressions at all and to leave this for run-time and caching.
I did some benchmarks and would like to hear your thoughts on this.
Using this small benchmark script (https://gist.github.com/dmaicher/ae506ff436a4647f3eaf7e59ec4c4aa1) I get the following numbers:
Using
NullAdapter
:Using
ArrayAdapter
for caching there is almost no difference:So on my laptop the difference for the
NullAdapter
case is roughly 20s for 500 thousand evaluations. Which means for one evaluation it's in the range of 40 microseconds or0.04ms
.Maybe we can make use of
cache.system
for the expression language on 3.3+?WDYT?