There is also SHIRO-417, which is somewhat related. I started applying the patch this morning, but I wanted to make sure we had a holistic solution (syntax, parameter annotation usage, etc), before continuing.
On Thu, Jul 7, 2016 at 10:51 AM, Lenny Primak <[email protected]> wrote: > Thanks, Brian! > > There you go, Richard, you can comment / upvote that one. > > On Jul 7, 2016, at 8:18 AM, Brian Demers <[email protected]> wrote: > > Take a look at this one: https://issues.apache.org/jira/browse/SHIRO-314 > > > On Thu, Jul 7, 2016 at 4:46 AM, Lenny Primak <[email protected]> > wrote: > >> Ok, you can open an enhancement JIRA with that. >> >> > On Jul 7, 2016, at 3:43 AM, Richard Adams <[email protected]> >> wrote: >> > >> > Well, Spring Security implements ACL; >> > >> http://docs.spring.io/spring-security/site/docs/3.0.x/reference/domain-acls.html >> >> On 7 Jul 2016, at 09:42, Lenny Primak <[email protected]> wrote: >> >> >> >> The tricky thing is to figure out what the common feature set actually >> is (i.e. to design it or take already existing design) >> >> Is there another framework that you know of or any existing project >> that implements this already? >> >> If this was such a desirable feature for lots of people, it would be >> hard to believe that this wasn’t already implemented somewhere. >> >> >> >>> On Jul 7, 2016, at 3:39 AM, Richard Adams <[email protected]> >> wrote: >> >>> >> >>> Yes, I take your point - Shiro has all the Core features you need to >> get started, it’s conciseness is one of its main attractions, and there’s >> certainly a strong argument to avoid feature bloat and unnecessary >> complexity. >> >>> But, perhaps it is the case, that if many Shiro users are >> independently having to extend Shiro to obtain additional similar >> functionality, then there is a case for considering adding to Shiro. >> >>> Richard >> >>>> On 7 Jul 2016, at 09:26, Lenny Primak <[email protected]> >> wrote: >> >>>> >> >>>> My sentiments exactly. >> >>>> >> >>>> There are a lot of SNACs (shiny new ACronyms) popping up every few >> months that “some other framework” may have that are “missing” from Shiro, >> >>>> like many variants of **BAC (which are very much too vaguely >> defined, and not in any way standard) >> >>>> All of this can easily be solved by a few lines of custom code (in >> custom realm etc.) >> >>>> You can’t possibly chase all those vague acronyms and succeed. >> >>>> >> >>>> Saying that, I am not opposed to adding some sort of additional >> abstraction layer for **BAC, but it has to be well defined. >> >>>> >> >>>> Here is what I see as viable options: >> >>>> - Write an implementation yourself on top of Shiro, get traction in >> the wild, and then contribute it to Shiro, if still makes sense. >> >>>> - Point out specific code / features / documentation in another >> framework that implements your feature that has traction in the industry, >> >>>> i.e. has proven useful in the wild, and propose inclusion of such >> specific functionality in Shiro. >> >>>> >> >>>>> On Jul 7, 2016, at 3:02 AM, Richard Bradley < >> [email protected]> wrote: >> >>>>> >> >>>>> Could you explain what the benefit of this is over just >> implementing those restrictions in plain old Java code directly? >> >>>>> >> >>>>> Each of the use cases you have given could be translated into plain >> old Java code more or less 1-1 and the resulting code would be: >> >>>>> 1. simpler >> >>>>> 2. more maintainable >> >>>>> 3. more accessible to newcomers (no new language needs to be learnt) >> >>>>> 4. benefit from IDE support and static analysis support >> >>>>> 5. likely more reliable (there are fewer moving parts; no AOP >> framework is needed etc.; no chance of bugs in the implementation of >> @RequiresAttributes or misunderstandings in its usage) >> >>>>> 6. easier to test >> >>>>> >> >>>>> The only downside I can see is that it might be slightly harder to >> statically verify that a developer has remembered to address security (in >> the proposed version you might be able to write a unit tests that asserts >> that all relevant methods have a non-empty "@RequiresAttributes" >> annotation). >> >>>>> >> >>>>> Here are the examples from below rewritten in POJ: >> >>>>> >> >>>>> Assume the following helper code is imported in each case: >> >>>>> >> >>>>> public class AuthenticationHelper { >> >>>>> public static void assertAuth(bool ok) { >> >>>>> if (!ok) { >> >>>>> throw new AuthenticationException("Insufficient permissions"); >> >>>>> } >> >>>>> } >> >>>>> >> >>>>> public static User currentUser() { >> >>>>> // create a domain-specific User class from Shiro's >> SecurityUtils.getSubject() >> >>>>> } >> >>>>> } >> >>>>> >> >>>>> Example of use case #1: >> >>>>> >> >>>>> public class ProfileEditor { >> >>>>> >> >>>>> // all users implicitly have permission to edit their own profile, >> >>>>> // so don't need RequiresPermissions, but we do need to check >> >>>>> // that the profile belongs to this user >> >>>>> public void store(Profile userProfile) { >> >>>>> assertAuth(currentUser().id == userProfile.userId); >> >>>>> >> >>>>> // TODO: store the changes >> >>>>> } >> >>>>> >> >>>>> } >> >>>>> >> >>>>> Example of use case #2: >> >>>>> >> >>>>> public class Project { >> >>>>> List<String> getMemberIds() { >> >>>>> // TODO: return list of member ids in this project >> >>>>> } >> >>>>> >> >>>>> // the user has role "project manager" with a "settings:edit" >> permission >> >>>>> // BUT... it's only for this project, not for all projects! >> >>>>> @RequiresPermissions("settings:edit") >> >>>>> public void editSettings(String key, String newValue) { >> >>>>> assertAuth(getMemberIds().contains(currentUser().id)); >> >>>>> >> >>>>> // TODO: change the setting >> >>>>> } >> >>>>> >> >>>>> } >> >>>>> >> >>>>> Example of use case #3: >> >>>>> >> >>>>> public class ClassifiedDocumentRepository { >> >>>>> >> >>>>> @RequiresPermissions("documents:store") >> >>>>> public void storeDocument(@Map("document") Document doc) { >> >>>>> assertAuth(currentUser().clearanceLevel >= >> document.clearanceLevel); >> >>>>> // TODO: store the document >> >>>>> } >> >>>>> >> >>>>> // applying access control on return value here with special >> variable $return >> >>>>> @RequiresPermissions("documents:retrieve") >> >>>>> public Document retrieveDocument(String documentId) { >> >>>>> // TODO: find the document and its metadata >> >>>>> >> >>>>> Document document = ... >> >>>>> >> >>>>> assertAuth(currentUser().clearanceLevel >= >> document.clearanceLevel); >> >>>>> return document; >> >>>>> } >> >>>>> >> >>>>> >> >>>>> } >> >>>>> >> >>>>> Best, >> >>>>> >> >>>>> >> >>>>> Rich >> >>>>> >> >>>>> >> >>>>> >> >>>>> -----Original Message----- >> >>>>> From: jbuhacoff [mailto:[email protected]] >> >>>>> Sent: 07 July 2016 05:19 >> >>>>> To: [email protected] >> >>>>> Subject: Attribute-based access control >> >>>>> >> >>>>> Hi, I've been using Shiro for a couple of years now in various >> projects with annotations and the wildcard permission syntax. Now I have a >> new requirement for ABAC, and I think it should be possible to add this >> capability to Shiro. >> >>>>> I have a proposal below, and wanted to get some comments. If >> there's interest, I would develop it myself and contribute the code & >> documentation. >> >>>>> >> >>>>> Here are some use cases: >> >>>>> >> >>>>> 1. a "my profile" or "my settings" feature: user should be able to >> edit own things but not everything in the table. >> >>>>> >> >>>>> 2. project or organization based permissions: user should be able >> to read documents in a project while user is associated with the project or >> team, possibly combined with a general "can read documents" permission. >> >>>>> >> >>>>> 3. clearance level: user has a "can read documents" permission but >> this needs to be matched with the user's clearance level and the document's >> clearance level. >> >>>>> >> >>>>> I see attribute-based access control as being a nice complement and >> orthogonal to the permission-based access control. A given method could be >> annotated with either one or both together to achieve the right level of >> control. >> >>>>> >> >>>>> My proposal is to add a new annotation @RequiresAttributes and >> to let its >> >>>>> value be a boolean expression to be evaluated. Of course the >> expression will need to be able to refer to the current user, the object in >> question, and maybe even other things like the time of day, the https >> client certificate, or whatever. Getting these bits of info into the >> context of the expression language would be a combination of three things: >> 1) the realm can set some context when the user is authenticated based on >> information available at that time (user attributes, connection attributes, >> etc.) , 2) there could be generic "attribute injectors" like for >> calendar/time, system properties, or other things that are neither user nor >> object in question; >> >>>>> 3) a new @Map annotation that can be applied to method parameters >> in order to give them a specific name in the expression. >> >>>>> >> >>>>> Also there is a special case when we might want to apply >> attribute-based permissions on the return value of a method. For this we >> have another annotation @RequiresAttributesOnReturn which would be applied >> with around advice, calling proceed() and then checking permissions using >> the return value of the original method bound to a special variable $return. >> >>>>> >> >>>>> Both @RequiresAttributes and @RequiresAttributesOnReturn would have >> corresponding methods that could be called directly from anywhere in the >> code in order to perform the same evaluation without annotations. >> >>>>> >> >>>>> Special variable $this would be available to expressions annotated >> on instance methods. >> >>>>> >> >>>>> Variables and methods of objects would be accessible via dot >> notation, with automatic use of bean-style "getter" methods when they exist. >> >>>>> >> >>>>> In all the following examples, $user is a variable bound by the >> authentication realm to a User object with methods String getId() and >> Integer getClearanceLevel(). >> >>>>> >> >>>>> Example of use case #1: >> >>>>> >> >>>>> public class ProfileEditor { >> >>>>> >> >>>>> // all users implicitly have permission to edit their own profile, >> >>>>> // so don't need RequiresPermissions, but we do need to check >> >>>>> // that the profile belongs to this user >> >>>>> @RequiresAttributes("$user.id = $profile.userId") >> >>>>> public void store(@Map("profile") Profile userProfile) { >> >>>>> // TODO: store the changes >> >>>>> } >> >>>>> >> >>>>> } >> >>>>> >> >>>>> Example of use case #2: >> >>>>> >> >>>>> public class Project { >> >>>>> List<String> getMemberIds() { >> >>>>> // TODO: return list of member ids in this project >> >>>>> } >> >>>>> >> >>>>> // the user has role "project manager" with a "settings:edit" >> permission >> >>>>> // BUT... it's only for this project, not for all projects! >> >>>>> // also special variable $this refers to enclosing class instance >> >>>>> @RequiresPermissions("settings:edit") >> >>>>> @RequiresAttributes("$this.memberIds.contains($user.id)") >> >>>>> public void editSettings(String key, String newValue) { >> >>>>> // TODO: change the setting >> >>>>> } >> >>>>> >> >>>>> } >> >>>>> >> >>>>> Example of use case #3: >> >>>>> >> >>>>> public class ClassifiedDocumentRepository { >> >>>>> >> >>>>> @RequiresPermissions("documents:store") >> >>>>> @RequiresAttributes("$user.clearanceLevel >= >> $document.clearanceLevel") >> >>>>> public void storeDocument(@Map("document") Document doc) { >> >>>>> // TODO: store the document >> >>>>> } >> >>>>> >> >>>>> // applying access control on return value here with special >> variable $return >> >>>>> @RequiresPermissions("documents:retrieve") >> >>>>> @RequiresAttributesOnReturn("$user.clearanceLevel >= >> >>>>> $return.clearanceLevel") >> >>>>> public Document retrieveDocument(String documentId) { >> >>>>> // TODO: find the document and its metadata >> >>>>> return document; >> >>>>> } >> >>>>> >> >>>>> >> >>>>> } >> >>>>> >> >>>>> >> >>>>> >> >>>>> >> >>>>> >> >>>>> >> >>>>> >> >>>>> -- >> >>>>> View this message in context: >> http://shiro-user.582556.n2.nabble.com/Attribute-based-access-control-tp7581093.html >> >>>>> Sent from the Shiro User mailing list archive at Nabble.com >> <http://nabble.com>. >> >>>>> >> >>>>> Richard Bradley >> >>>>> Tel : 020 7485 7500 ext 3230 | Fax : 020 7485 7575 >> >>>>> >> >>>>> softwire >> >>>>> Sunday Times Best Small Companies - UK top 25 six years running >> >>>>> Web : www.softwire.com<http://www.softwire.com/> | Follow us on >> Twitter : @SoftwireUK<https://twitter.com/SoftwireUK> >> >>>>> Addr : 110 Highgate Studios, 53-79 Highgate Road, London NW5 1TL >> >>>>> Softwire Technology Limited. Registered in England no. 3824658. >> Registered Office : Gallery Court, 28 Arcadia Avenue, Finchley, London. N3 >> 2FG >> >>>>> >> >>>> >> >>> >> >> >> > >> >> > >
