Account Store Implementation

76 views
Skip to first unread message

Michael Robellard

unread,
Mar 31, 2016, 1:37:16 PM3/31/16
to Yosai
I like what I see in the documentation and it just so happens that I am currently dealing with building an Authorization system in my project, so I am thinking about giving Yosai a try. I have been digging through the code to try and figure out what steps I need to take. Once I figure this out I would be happy to help document it since the documentation is a little light in a few areas around what you need to do to set up your own account store if the provided Alchemy Store Won't work for you. 

From looking at the Alchemy Store and using it as an example, It looks like the main things that need to be done to use your own database design (I already have one that supports hierarchal roles) is that you need to have 3 queries to run:

  1. get_permissions_query: Gets all the permissions for a subject (UserModel in the sqlalchemy example), returns them as a list of strings In the style Domain:action:resource. The issue I am having here is this doesn't match the examples you have on http://yosaiproject.github.io/yosai/authorization/ where you say it is 'domain:action:instance', my assumption was that instance and resource where synonyms in this case, but then I looked at your example:
1) 'subreddit_id123:submission:remove'
2) 'subreddit_id123:comment:remove'

here it seems like the action and resource/instance are swapped. So my next step was to look at the permission checking functions and at first glance it appears that it doesn't really matter what format you use for the permission string and it is just comparing them for equality to the ones supplied by your call to check_permission or related functions, with some nice variable substitution in the dynamic case (very nice by the way, I was trying to figure out how I would do that if I had to implement that myself). Then I see the WildcardPermission thing (which isn't even mentioned in the documentation) and now I am a little more confused, although I think I may have  a handle on it now. What I think the documentation is supposed to explain:

Assuming you are using the supplied Permission Class, Permissions are represented as strings in the form 'domain:action:z' where domain, action or z can be comma separated lists or * which imply match any string. When checking a permission that a subject has against a required permission it checks each of the three parts and as long as any of the comma separated subparts match the subpart in the required permission its considered a match.

I think my understanding is right, but I am not 100% certain. I used z in my example because I have seen three different words for that last part (target, instance, resource) please pick one and be consistent. 

2. 
 
 

Michael Robellard

unread,
Mar 31, 2016, 1:52:37 PM3/31/16
to Yosai
Shit, It accidentally posted before I was done
2. get_roles_query just returns a list of RoleModel instances, but has_roles takes a list of strings. How do you identify the RoleModels?

3. get credential_query returns a list of CredentialModel instances, how does that work? 

I think globally the issue is that the resolver stuff hasn't been explained anywhere, but I could just be lost.

I am wondering if your use of Abstract Base Classes which are generally not used or required in Python is adding to the confusion, I understand that they are standing in for interfaces in Java, but I have never seen a large Python project make use of ABCs.

Also can you run sphinx or something similar to generate API docs for your code. You have quite good docstrings in your code but none of it is visible on the documentation website.

All in all I like the project and I think it could be way better to use than using my homegrown stuff that does the same thing. Thanks for the hard work

Mike 

Darin Gordon

unread,
Mar 31, 2016, 2:25:46 PM3/31/16
to Yosai
Hey Michael

First, thanks for checking Yosai out and considering it for your work.  I am open to constructive feedback but would prefer that discussion leads to pull requests. I see this project as having reached its first milestone on my own effort but it will reach the next milestone based on collective effort.

When I ported Apache Shiro, I honored its interface-driven architecture, at least a lightweight version of it, by porting interfaces to abstract base classes and declaring abstractmethods required of each API.  Yosai_AlchemyStore is a quick-start extension, and one that helped with integration testing.  To replace it, you'd follow the same api as defined in the AccountStore abc.  Note that I've defined *two* "interfaces" -- one for credentials and another for authorization, in case a single AccountStore doesn't offer both.  It's a simple API.  

Note that ABC's are staying in, for now.  If anything, I may enforce their use more strictly.  The python community doesn't have a consensus about how to implement them (abc's, zope.interfaces, raising notimplementederror).  Rather than add another dependency for zope.interfaces, I chose abc's.  The intent of their use is to honor the inversion of control principle.

I suspect you may have come across a documentation bug, which will be fixed/clarified, but it seems you managed to understand the big picture any way.

DefaultPermission inherits from WildcardPermission.  It names/labels the parts of a permission (domain , action, instance) , which later makes possible for indexed lookup of permissions.  The more permissions a user has, the more items that would need to be iterated over to check for authorization.  I reduce, or at least have tried to reduce, the overhead with indexing and keying on "domain":  http://bit.ly/1RNKBu1

Thanks regarding the dynamic permission design.  It's based on sage advice solicited from Graham Dumpleton, who is a decorator jedi master.

Resolvers are straight from the Shiro playbook.  It's a design pattern where a class need not know what type of class to use.  Their definition trickles down from the SecurityManager, as do all other objects shared across classes:  http://bit.ly/1MWDazA
I'm not committed to keeping them if they present themselves as boilerplate, replacing resolvers with their hard coded classes that I've defined as their defaults.  I was hesitant to remove them as I ported a 10+ year battle tested project and they may serve good use in practice.

If I run sphinx on all of this source code, it will create a mountain of documentation.  Is this kind of documentation useful -- would you actually go through it like that?



On Thursday, March 31, 2016 at 1:37:16 PM UTC-4, Michael Robellard wrote:

Michael Robellard

unread,
Mar 31, 2016, 2:53:57 PM3/31/16
to Yosai
Yes that type of documentation is immensely useful, particularly because once you have it you can link to it from your more general documentation and we can see exactly what the APIs are and what the parameters are etc... The best documentation has example driven documentation like you have with links to actual api documentation derived the code and docstrings, with links to the source code, that way it is easy to go as deep as you need to to understand what is going on.
Reply all
Reply to author
Forward
0 new messages