[Grok-dev] Data modelling & security

Martijn Faassen faassen at startifact.com
Thu Jan 20 17:06:41 EST 2011


On 01/17/2011 02:34 AM, Matthias wrote:

> 1) Does the basic version or the alternative version make more sense? The
> alternative version clearly marks any missing data. I am not sure if
> that's good or bad.

I'm not sure I understand the intent of the tables you mention. I mean, 
if Task and User are accessible, why would you return the task and the 
user? Is that because the assignment is inaccessible and you're actually 
querying for assignments? Could you model this then so that the 
Assignment permissions are the only ones directly checked, but you let 
them derive from the underlying task and user (and their own permission)?

> 2) Each intermediate query result would need to be security checked. If
> you think checking the resulting objects sufficed, just imagine the
> results of the following query: "get any user where task == 'top secret'".
> You'd get a list of users involved with that task even if though nobody
> should've known that those users were assigned to the task.

The question is whether this is in fact a query for a user at all. Isn't 
this really a query for "get all assignments where task == "top secret"? 
 From the assignments you can derive the users, yes, but is this really 
the target of the query?

Anyway, I think it'd be interesting to set up at least a custom 
PermissionMap for Assignment, and perhaps the others.

from zope.securitypolicy.interfaces import IPrincipalPermissionMap
from zope.security.management import checkPermission

class MyPermissionMap(grok.Adapter)
     grok.context(Assignment)
     grok.provides(IPrincipalPermissionMap)

     # this is really the only method you have to implement, even though
     # the interface defines more....
     def getSetting(self, permission_id, principal_id, default=Unset)
          if not checkPermission(permission_id, self.context.user):
              return Unset
          ...

You probably have to watch out for crazy recursion issues in some cases, 
so perhaps instead of checkPermission you should go to a lower-level.

> 3) Resulting from 2) there might arise performance problems. I am not sure
> if the query could be performed while collecting the necessary permissions
> for each "row" in the result. Then one could check permissions only at the
> end (and possibly against some form of index to speed things up or the
> "top 10" of the results).

I think doing the permission checks in the end is a lot easier to get 
right, and probably will perform better too.

> 4) If a user is generally accessible, it should not return the "password"
> attribute of the User except if the user is the querying user. I guess
> this can be solved with zope.proxy/zope.security. Or by turning the
> password attribute to a "PasswordProtected" relation between a user and
> its password, then the relation can be protected at the object level, just
> like the Assignment

You could of course try solving this issue in the user interface as 
opposed to on the code level. The question here you have is how much do 
you trust the developers. Do you really not trust them enough to want to 
hide the password attribute? Is that either because they're too evil 
(okay, give up already) or because they're too stupid?

> How do you guys deal with these problems? I'd really like avoid having to
> write a special grok.View and explicitly checking permissions for each
> operation the client might perform. If the queries could be all dynamic I
> could a) develop faster, b) had less redundant code and c) clients could
> create their own UIs/queries for their tasks.

I've recently mostly had to deal with these problems when exposing 
SQLAlchemy objects, and PermissionMap works pretty well then. You can do 
whatever database query you need to determine whether someone has a 
permission.

You could do something similar: instead of using Zope's permissions you 
could instead use your own database structures (attributes) to talk 
about permissions in a way that is sensible to your application, and 
then use PermissionMap to translate these to permissions so that views 
show up or not. You could then use these attributes in your queries 
directly.

You should only go for heavy-duty security proxies if you really don't 
trust your developers in some way. There's not a lot of experience with 
dealing this in a Grok context, but you should be able to make it work. 
You might have to disable Grok's custom publisher.

I know it's tempting to get the security architecture right at a lower 
level. Zope 3 (and the ZTK) was designed to allow this kind of stuff, 
using the proxies. When we started the Grok project, I argued much for 
loosening some of these rules, because getting the security model right 
up-front (for all your methods and attributes) ends to take up a lot of 
time and effort that can really be a drag on development, and during 
early development you often don't even know enough about your data model 
yet to get it right. A lot of usability issues...

That said, it might be possible to design a more lower level security 
system that is more usable. It might also be that in some projects, the 
investment in effort in the existing system is worth it.

> Additionally, are there any comparable systems which feature full objects
> like the ZODB does, yet allowing fully dynamic queries with fine-grained
> security? It might be worth "stealing" from them :-)
>
> Is it even advisable to be able to query the ZODB in the way outlined
> above?

It's a matter of trade-offs.

> Finally, is anybody else interested in features like this? Right now it
> seems this could make your client side coding a lot easier, especially if
> you have generic javascript widgets for lists, tables, forms and so on.

I guess you're not satifisfied by just making sure your JSON methods are 
protected and don't deliver too much data? :)

Thanks for bringing up this discussion! It's hard to get into, but it's 
quite interesting!

Regards,

Martijn



More information about the Grok-dev mailing list