Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Security] Be able to know the reasons of the denied access#35592

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
maidmaid wants to merge9 commits intosymfony:masterfrommaidmaid:vote

Conversation

maidmaid
Copy link
Contributor

QA
Branch?master
Bug fix?no
New feature?yes
Deprecations?yes
Tickets#27995,#26343
LicenseMIT
Doc PR/

About the voters, the gif of the the original issue sums up the situation well :

gif

Currently, the voters can only say yes or no. This PR allows to give a reason from the voters.

Before :

class PostVoterextends Voter{// ...protectedfunctionvoteOnAttribute($attribute,$subject,TokenInterface$token)    {if ($subject->getAuthor() !==$token->getUser()) {returnfalse;        }if ($subject->getStatus() !=='draft') {returnfalse;        }returntrue;    }}

After :

class PostVoterextends Voter{// ...protectedfunctionvoteOnAttribute($attribute,$subject,TokenInterface$token)    {if ($subject->getAuthor() !==$token->getUser()) {return$this->deny('You are not the author.')        }if ($subject->getStatus() !=='draft') {return$this->deny('The post is no more a draft.')        }return$this->grant();    }}

A voter returns no more an int based on the constantACCESS_{GRANTED,ABSTAIN,DENIED} but aVote object which contains the access result and the reason. Thus, the security panel of the profiler can display the reason of each vote.

profiler

The access decision manager returns no more a bool for the final verdict but anAccessDecision object which contains the final verdict and all the votes. Thus, the 403 response can display all the denied raisons.

exception

It's in a PoC state. Todo : BC layer, migration of the others voters, update current tests, add new tests...

Pierstoval, ktherage, GaetanRole, noniagriconomie, xelan, maxhelias, vtsykun, deguif, scroach, stephanvierkant, and 8 more reacted with thumbs up emojiPierstoval, Koc, scroach, stephanvierkant, and deguif reacted with hooray emojiPierstoval, OskarStark, JodyLognoul, scroach, ShiNoSenshi, zajca, and deguif reacted with heart emojiPierstoval and deguif reacted with rocket emoji
Copy link
Contributor

@PierstovalPierstoval left a comment

Choose a reason for hiding this comment

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

I like this PR very much 😄 I hope it's gonna be appreciated by the core team!
In the meantime I have a few comments :)

maidmaid and Warxcell reacted with heart emoji
Copy link
Contributor

@ro0NLro0NL left a comment

Choose a reason for hiding this comment

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

we should re-evaluate#21094 (comment) first

AccessDecision vsVote is confusing, there should be only 1 IMHO. AFAIK there's no real reason to merge multiple votes now, which is a new behavior

/**
* Sets an access decision and appends the denied reasons to the exception message.
*/
public function setAccessDecision(AccessDecision $accessDecision)
Copy link
Contributor

Choose a reason for hiding this comment

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

this cannot be stateful IMHO

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

What do you suggest ?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

We could make it stateless and have a specific exception render for AccessDeniedException. WDYT ?

@maidmaid
Copy link
ContributorAuthor

AccessDecision vs Vote is confusing, there should be only 1

We need a distinction between 1 vote amongst others and the final decision. E.g. 3 votes in + 4 votes against = decision to deny (in a consensus strategy). So, a voter votes (it returns aVote object), whereas the access decision manager decides the final access (it returns anAccessDecision object). Maybe,AccessDecision could be renamed to something likeVerdict for clarity ?

@chalasrchalasr added this to thenext milestoneFeb 5, 2020
@chalasr
Copy link
Member

chalasr commentedFeb 5, 2020
edited
Loading

AccessDecision could be renamed to something like Verdict for clarity ?

Not sure it would bring much:AccessDecisionManager takes access decisions,verdict is just a synonym, might be more confusing than helpful.

{% endif %}
</td>
<td class="font-normal text-small">{{ voter_detail['vote'].reason }}</td>
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe only display if not empty reason?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Thetd html node must always be present.

Copy link
Member

Choose a reason for hiding this comment

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

I believe we are used to display~ or(unknown) to not let it blank. Could you check and apply what looks better?

noniagriconomie, maidmaid, and vasilvestre reacted with thumbs up emoji
Copy link
ContributorAuthor

@maidmaidmaidmaidMar 3, 2020
edited
Loading

Choose a reason for hiding this comment

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

image
Much better imo ;)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

@javiereguiluz would you have a suggestion here maybe ?

@maidmaidmaidmaidforce-pushed thevote branch 2 times, most recently from2261746 to69e8d07CompareFebruary 18, 2020 10:31
@maidmaid

This comment has been minimized.

trait AccessTrait
{
/** @var int */
protected $access;
Copy link
Member

Choose a reason for hiding this comment

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

Should be private.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Already discussed here#35592 (comment). Ok for you ?

Copy link
Member

Choose a reason for hiding this comment

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

Not sure to understand the rationale there.
If a class uses this trait, it does have write access to the private properties defined by the trait. Usingprotected would only serve for inheritance purpose, which is not needed here AFAIK.
Am I missing something?

maidmaidand others added6 commitsMarch 3, 2020 09:42
Co-Authored-By: Antoine Makdessi <antoine.makdessi@agriconomie.com>
Co-Authored-By: Antoine Makdessi <antoine.makdessi@agriconomie.com>
Co-Authored-By: Antoine Makdessi <antoine.makdessi@agriconomie.com>
@maidmaid
Copy link
ContributorAuthor

maidmaid commentedMar 3, 2020
edited
Loading

Changes committed from your feedbacks, thanks !

This PR looks appreciated and its design seems validated, so I'm gonna complete it by writting the tests soon.

noniagriconomie reacted with thumbs up emoji

@@ -11,13 +11,22 @@

namespace Symfony\Component\Security\Core\Authorization\Voter;

/**
* A Vote is returned by a Voter and contains the access (granted, abstain or denied). It can also contains a reason
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* A Vote is returned by a Voterandcontains the access (granted, abstainor denied). It can also contains a reason
* A Vote is returned by a Voterandcontains the access (granted, abstainor denied).
* It can also contains a reason explaining the vote decision.

@stephanvierkant
Copy link
Contributor

Thanks for create this PR!

What about creating multiple reasons to deny access, like you can with workflows?

Copy link
Member

@wouterjwouterj left a comment
edited
Loading

Choose a reason for hiding this comment

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

I like this idea. I think I also agree on the difference betweenVote andAccessDecision. An access decision is a collection of votes.

As commented, there is a need for BC layers in the usage part. I guess the only possible method to change this would be to create a new method/new interface.In that case, I think it makes sense to also think a little bit about how we're going to solve#28868 (comment) in the future, as it might also require a different authorization API. If we need to create a new authorization API for this change, I think it's best to take that change into account as well (not fix it in this PR, but designing an API that allows it to happen without change).On second thought, let's not combine these things and only focus on this feature. The other issue can be implemented using the current interface as well.

@@ -33,7 +33,7 @@ interface VoterInterface
* @param mixed $subject The subject to secure
* @param array $attributes An array of attributes associated with the method being invoked
*
* @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
* @return int|Vote either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
Copy link
Member

Choose a reason for hiding this comment

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

The same thing applies here: I don't think we can change the method return signature fromint toVote, as it'll impact how you need to use this method.

@@ -26,7 +26,7 @@ interface AccessDecisionManagerInterface
* @param array $attributes An array of attributes associated with the method being invoked
* @param object $object The object to secure
*
* @return bool true if the accessisgranted, false otherwise
* @return bool|AccessDecision Returning a booleanisdeprecated since Symfony 5.1. Return an AccessDecision object instead.
Copy link
Member

Choose a reason for hiding this comment

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

This interface is not internal, so we should also be BC with the usage of the method AFAIK. I don't think we currently preserve backwards compatibility in e.g. this example:

if (!$accessDecisionManager->decide(...)) {thrownewAccessDeniedException();}

If anAccessDecision::createDenied() is returned, the condition!(AccessDecision::createDenied()) isfalse, causing the access denied exception not to be throw (while it was thrown using the oldbool signature).

$this->lastAccessDecision = $this->accessDecisionManager->decide($token, [$attribute], $subject);

if (\is_bool($this->lastAccessDecision)) {
trigger_deprecation('symfony/security', 5.1, 'Returning a boolean from the "%s::decide()" method is deprecated. Return an "%s" object instead', \get_class($this->accessDecisionManager), AccessDecision::class);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
trigger_deprecation('symfony/security',5.1,'Returning a boolean from the "%s::decide()" method is deprecated. Return an "%s" object instead',\get_class($this->accessDecisionManager), AccessDecision::class);
trigger_deprecation('symfony/security-core',5.1,'Returning a boolean from the "%s::decide()" method is deprecated, return an "%s" object instead',\get_class($this->accessDecisionManager), AccessDecision::class);

private function vote(VoterInterface $voter, TokenInterface $token, $subject, array $attributes): Vote
{
if (\is_int($vote = $voter->vote($token, $subject, $attributes))) {
trigger_deprecation('symfony/security', 5.1, 'Returning an int from the "%s::vote()" method is deprecated. Return a "%s" object instead.', \get_class($this->voter), Vote::class);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
trigger_deprecation('symfony/security',5.1,'Returning an int from the "%s::vote()" method is deprecated. Return a "%s" object instead.',\get_class($this->voter), Vote::class);
trigger_deprecation('symfony/security-core',5.1,'Returning an int from the "%s::vote()" method is deprecated, return a "%s" object instead.',\get_class($this->voter), Vote::class);

return new self(VoterInterface::ACCESS_DENIED, $reason, $parameters);
}

public function merge(self $vote): void
Copy link
Member

@wouterjwouterjApr 24, 2020
edited
Loading

Choose a reason for hiding this comment

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

I don't really see the value of this method. It doesn't fullfill what I would call "merge" (i.e. it only merges the reason, what happens if we pass denied into the merge of a granted vote?) and it's used only in one specific case. I would rather add asetReason() method and doing this directly in the voter.

@fabpot
Copy link
Member

@wouterj@maidmaid What would be the next steps to move this PR forward?

@wouterj
Copy link
Member

I thinkthis comment from my review is the most important: How can we make this change BC?

@deguif
Copy link
Contributor

Will we be able to get in in next release before feature freeze?

@fabpot
Copy link
Member

@deguif Depends on when it's ready to be merged. We still have 2 weeks for 5.2.

@noniagriconomie
Copy link
Contributor

@maidmaid@wouterj@fabpot

Cant we use the same logic as thehttps://github.com/symfony/symfony/blob/master/src/Symfony/Component/EventDispatcher/LegacyEventDispatcherProxy.php?

a proxy class that handles previous/new voting feature? (I am unsure if it can be applied here)

concerning the feature itself, i think it is usefull :) (like the workflow transition blocker)

(i can help test it if needed :))

@dkarlovi
Copy link
Contributor

This seems like very close to what was done for Workflow, guards got the same ability there from setting a boolean value, likely the same approach can be taken.

@fabpot
Copy link
Member

@maidmaid Still interested in working on this? This can still be part of 5.2 if approved before tomorrow.

@maidmaid
Copy link
ContributorAuthor

Sorry for the delay. I missed the 5.2 train I guess. I'm gonna resume this work soon. Let's wait 5.3 :)

stephanvierkant and JodyLognoul reacted with hooray emoji

@fabpotfabpot closed thisOct 7, 2020
@fabpot
Copy link
Member

We've just moved away frommaster as the main branch to use5.x instead. Unfortunately, I cannot reopen the PR and change the target branch to5.x. Can you open a new PR referencing this one to not loose the discussion? Thank you for your understanding and for your help.

@noniagriconomie
Copy link
Contributor

@maidmaid friendly ping,
are you able to complete this code for the next version 5.3? If not, can help be provided?
(related to#27995 (comment) and following comments)

deguif reacted with thumbs up emoji

@maidmaid
Copy link
ContributorAuthor

@noniagriconomie I don't have a lot of time to finish this work. I would be happy if someone finished it :)

@azjezz
Copy link
Contributor

Hey@maidmaid, i would like to pick up where you left here and continue working on this PR, is that okay with you?

chalasr, noniagriconomie, and maidmaid reacted with thumbs up emoji

@noniagriconomie
Copy link
Contributor

@azjezz i would be pleased to help you, review or testing in real project if you need :)

@azjezz
Copy link
Contributor

@ noniagriconomie see#40711

alamirault added a commit to alamirault/symfony that referenced this pull requestMay 26, 2022
fabpot added a commit that referenced this pull requestFeb 17, 2025
…e (nicolas-grekas)This PR was merged into the 7.3 branch.Discussion----------[Security] Add ability for voters to explain their vote| Q             | A| ------------- | ---| Branch?       | 7.3| Bug fix?      | no| New feature?  | no| Deprecations? | no| Issues        |Fix#27995,#26343,#35592,#43147| License       | MITThis PR takes over#58107, which itself took over from#46493, etc.It takes the only approach I could think of that would preserve BC.The visible tip of what this achieves is:![image](https://github.com/user-attachments/assets/67bd0678-868f-40ed-b2c6-3b1f10ffe101)![image](https://github.com/user-attachments/assets/715814d8-e4de-47f0-aa0e-c412092389ff)Internally, this provides a new access audit log infrastructure that relies on new `AccessDecision` and `Vote` objects.Note that I didn't add (nor fix) tests for now. I'll borrow (and credit) from#58107 /#46493 as much as possible.Commits-------c6eb9ae [Security] Add ability for voters to explain their vote
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@wouterjwouterjwouterj left review comments

@OskarStarkOskarStarkOskarStark left review comments

@ro0NLro0NLro0NL left review comments

@PierstovalPierstovalPierstoval left review comments

@chalasrchalasrchalasr left review comments

@noniagriconomienoniagriconomienoniagriconomie left review comments

Assignees
No one assigned
Projects
None yet
Milestone
5.4
Development

Successfully merging this pull request may close these issues.

14 participants
@maidmaid@chalasr@stephanvierkant@fabpot@wouterj@deguif@noniagriconomie@dkarlovi@azjezz@OskarStark@ro0NL@Pierstoval@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp