Hi!

Great discussion! :-)


Gustavo Narea schrieb:
> Hello.
> 

[...]

>> So I'll just note that calling "permissions" and "groups" out as
>> specialized metadata passed down through who is really a TG thing, and not
>> an "any framework" thing.  No other framework I've used calls "permissions"
>> what you call them in TG2 (in Zope, they might be called "roles", although
>> I'm not sure there's a complete one-to-one mapping).
> 
> Yes, I agree with you. But I think the "users, groups and permissions" 
> pattern 
> is becoming a rather famous pattern, so hopefully many people will feel like 
> at home.

I haven't looked at it in detail but as you mentioned OAuth as well I 
wanted to point out that those things attached to an access token might 
be very fine grained permissions like I allow somebody to see my 
fullname but not my email address.. I am not sure this will be modelled 
with having a permission for each profile field (profile is just an 
example anyway).

So in this case I'd like to get the actually token key and let the app 
decide what it means.

Not sure this is an issue but I wanted to point it out :)

cheers,

Christian


> 
>>> So, you only need one metadata provider that "knows" how to find the
>>> groups and permissions from different sources. For example, you could use
>>> the code below:
>>>     from repoze.who.plugins.htpasswd import HTPasswdPlugin, crypt_check
>>>     from tgext.authorization.middleware import setup_auth
>>>     # Please note that the plugins below have not been created yet; want
>>> to # jump in?
>>>     from tgext.authorization.plugins.htgroups import HtgroupsAdapter
>>>     from tgext.authorization.plugins.ini import IniPermissionAdapter
>>>
>>>     # Defining the group adapters; you may add as much as you need:
>>>     groups = {'all_groups': HtgroupsAdapter('/path/to/groups.htgroups')}
>>>
>>>     # Defining the permission adapters; you may add as much as you need:
>>>     permissions = {'all_perms':
>>> IniPermissionAdapter('/path/to/perms.ini')}
>>>
>>>     # repoze.who authenticators; you may add as much as you need:
>>>     htpasswd_auth = HTPasswdPlugin('/path/to/users.htpasswd',
>>> crypt_check) authenticators = [('htpasswd', htpasswd_auth)]
>>>
>>>     app_with_auth = setup_auth(
>>>         app,
>>>         groups,
>>>         permissions,
>>>         authenticators)
>>>
>>> Where setup_auth() is the function that configures repoze.who by loading
>>> tgext.authorization's AuthorizationMetadata.
>> Yep.  I might do this instead in who.ini:
>>
>> [plugin:ini_permissions]
>> use = my.package.ini_permissions:make_ini_permissions
>> path = /path/to/perms.ini
>>
>> [plugin:htgroups]
>> use = my.package.htpasswd_groups:make_htgroups
>> path = /path/to/groups.htgroups
>>
>> [plugin:htpasswd]
>> use = my.package.htpasswd_groups:make_htgroups
>> filename = /path/to/passwd
>> check_fn = repoze.who.plugins.htpasswd:plain_check
>>
>> [mdproviders]
>> plugins = htgroups ini_permissions
>>
>> [authenticators]
>> plugins = htpasswd
>>
>> Note that in this configuration there is *no* shared configuration between
>> any plugin.  IMO, that's a clue that it's not as common as might justify a
>> lot of machinery to elide it.
> 
> Hmm, after reading the code above, I think your suggestion of making them 
> independent metadata providers will be a great idea. But, at this point, I 
> think it's best to make it an alternate way, not the only one.
> 
> For example, I would add the following method to the BaseSourceAdapter:
>     class BaseSourceAdapter(object):
>         """This is the base class for source adapters"""
>         # ...
>         def add_metadata(self, environ, identity):
>             # because the "sections" in a "group source" are the groups
>             # defined for the application, find_sections() will load into
>             # the identity dict the groups to which the authenticated user
>             # belongs
>             if 'groups' not in identity:
>                 identity['groups'] = self.find_sections(identity)
>             else:
>                 identity['groups'] |= self.find_sections(identity)
> 
> So that groups/permission source adapters can also be used as independent 
> repoze.who metadata providers, as in your example.
> 
> 
>>> And you also get a bonus: The ability to manage your groups and
>>> permissions under a source-independent API, either from your application
>>> or from an external program.
>> I'd strongly suggest holding off on a "one-API-to-rule-them-all"
>> metadata-mutation capability until you have at least four or five backends
>> that can be mutated this way.  I've seen some truly horrific things come
>> out of conflating authentication / authorization with "member data
>> management" early-on, even if the member data being mutated is limited to
>> only authentication-and-authorization-related attributes; yes, I'm looking
>> at you, Plone. ;-)  It's easy enough to code up an application to change
>> these things independently, and by reading the code and docs I can see that
>> it's not really a "core" functionality yet.
> 
> You make a good point.
> 
> But I think it'll work here because it's a very simple API that doesn't try 
> to 
> do anything advance at all. It just deals with simple many-to-many relations 
> between the following entities:
>  * Users <-> groups: It's able to add or remove users from a given group.
>  * Groups <-> permissions: It's able to add/grant or remove/deny permissions 
> to a given group.
> 
> And it can also create, rename and delete groups and permissions. Nothing 
> more.
> 
> I think all of the actions above will be available on every supported source. 
> (When I started working on tgext.authorization, both groups and permissions 
> could have descriptions, but later I removed this "feature" because it would 
> turn into a headache depending on the source -- what about htgroups files? 
> The 
> only thing you can define in such groups are usernames, unless you insert 
> descriptions as comments before every group definition, which would be an 
> awful solution)
> 
> But you've hit the nail on the head! :) I think this *could* really be a TG-
> specific thing.
> 
> 
>>> The approach I'm taking with tgext.authorization, which is out of the
>>> scope of authorization itself, is to make it also setup authentication
>>> via repoze.who so that others won't have to repeat auth settings.
>> I'm not sure this is such a great idea.  Conflating configuration between
>> the two is a tradeoff: you don't repeat yourself, but it forms bonds
>> between plugins that may not stand the test of time.  At least if you keep
>> them separate, you don't paint yourself into any *particular* corner from
>> the start.  And if the configuration machinery allows for some form of
>> substitution, and it's used to prevent duplication during configuration,
>> it's far easier to stop using it than to change the authentication
>> machinery to not conflate the two things together.
> 
> Sorry, my statement above is not complete: Yes, tgext.authorization tries to 
> avoid people repeat settings, *but* it does so through optional utilities 
> which are used in TG2 unless told otherwise. If fact, it's easy to configure 
> everything separately instead of using such quick-start functions -- you can 
> even setup repoze.who yourself with support for tgext.authorization, without 
> having tgext.authorization doing so for you.
> 
> 
>>> See, for example, the
>>> function that configures authentication and authorization in the
>>> situation described above (users' credentials, groups and permissions
>>> stored in a database), called setup_sql_auth():
>>> http://trac.turbogears.org/browser/projects/tgAuthorization/trunk/tgext/a
>>> uthorization/quickstart.py
>>>
>>> The same would happen if I want to use LDAP authentication and re-user my
>>> LDAP's Organizational Units as groups in my application.
>> I'd argue that saying:
>>
>> [plugin:ldapauthentication]
>> base_dn = o=mycompany,c=US
>>
>> [plugin:ldapgroups]
>> base_dn = o=mycompany,c=US
>>
>> [plugin:ldappermissions]
>> base_dn = o=mycompany,c=US
>>
>> ... wouldn't really be so bad.  I could live with it.  And needing to
>> change it in only one place would be almost solved entirely if you could
>> do:
>>
>> %define BASE_DN = o=mycompany,c=US
>>
>> [plugin:ldapauthentication]
>> base_dn = ${BASE_DN}
>>
>> [plugin:ldapgroups]
>> base_dn = ${BASE_DN}
>>
>> I'm not married to who.ini format, BTW.  It's just what we have.
> 
> Yes, I think this wouldn't be an issue since group/permission source adapters 
> will be able to act as r.who MD providers too.
> 
>>>> To be honest, I'd like to keep authentication and authorization (at
>>>> least nontrivial-policy-based authorization) in separate packages in
>>>> order to avoid the fate of AuthKit, which tries to do both, and fails. 
>>>> I think it's a bit too much of a mental jump for some people to
>>>> understand the difference between the two without someone spelling it
>>>> out for them, and package separation tends to do that.
>>> I agree, but my idea is to have repoze.who part of main "WSGI Auth*"
>>> project, where it could also be used independently of the authorization
>>> framework, while the authorization framework does fully depends on the
>>> authentication system.
>> Like I mentioned above, the TG assumptions about the components that form
>> authorization are not really globally applicable.  If there should be such
>> a beast as a "WSGI Auth*" project, I suspect we should try to boil away the
>> bits that *are* globally applicable for authentication (if any).  My
>> personal suspicion is that we'll wind up with the empty set.
> 
> Yes, I think you're right. That crazy idea of the big Auth* project is gone 
> ;-)
> 
> Before I wrote this email, I think we didn't agree with two things:
>   1.- You preferred to have several group/permission metadata providers, 
> instead of one MD provider that loads everything from many places. I think 
> this is resolved with so-called "source adapters" being able to act as 
> repoze.who MD providers - what do you think?
>   2.- You didn't find a good idea to try to have these source adapters able 
> to 
> edit the sources under a common API as you thought it'd not be feasible.
> 
> So, since the first issue is resolved (I think so) and if I made you change 
> your mind regarding the second issue, would you agree with the creation of 
> the 
> repoze.what project as the successor of tgext.authorization? 
> 
> Cheers!

_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to