Fine grained/Object-level security example

114 views
Skip to first unread message

Mark Huang

unread,
Jun 16, 2012, 8:27:18 AM6/16/12
to pylons-...@googlegroups.com
Hi,

I am developing an ERP application and the authorization requirements are crazy complicated.  I'm pretty sure I need object-level security as stated in the Auth tutorial of Pyramid by Michael Merickel.  The problem is that it's my first time doing this and I'm a bit overwhelmed by this.

So....I have Products, Orders and Customers.  A logged in user can either belong to a group called "Backoffice" or "Agent".  "Backoffice" is actually an Admin who can do pretty much everything.  "Agent" is a bit tricky, and this is my problem. 

My understanding from Michael's tutorial is that you place the most general (this is also the group-level security stuff) ACLs in the Factories and the more specific ones as ACL properties in the object classes that the factories return.  Is this correct so far?

I have this business requirement that just makes my head explode:  "An agent can view, create, edit and delete (if these are the only permissions in the system, then this means ALL_PERMISSIONS right?) customers.  However, he can only view customers that belong to the same country as the agent's address."  Here's an attempt to setup the factory and customer object:

class CustomerFactory(object):

    __acl__= [
           (Allow, 'Backoffice', ALL_PERMISSIONS)     <---- THE GENERAL STUFF
    ]


    __name__ = "CustomerFactory"
    __parent__ = None

    def __init__(self, request):
        self.request = request

    def __getitem__(self, id):
        if id == "list":
            new_customer = CustomerModel()
            new_customer.__parent__ = self
            new_customer.__name__ = id
            return new_customer

class Customer(object):
   @property
   def __acl__(self):
       return [
           (Allow, 'Agent', ALL_PERMISSIONS)
       ]
   
Then in my code I would have to (1) find whether the current logged in user is an Agent, (2) find which country he is from and finally (3) filter the list of customers in the database based on the country.  Is this the correct way OR is there a much better and smarter way to do this?  To my understanding it seems that the Pyramid authorization only handles what a given user can do, be it edit/view/create/delete.  If we want to limit what the user can view, this has to be handled in the views. 

Daniel Holth

unread,
Jun 18, 2012, 10:19:36 AM6/18/12
to pylons-...@googlegroups.com
One way to do this might be to give the agent a principal like Country:US (the two letter country code of the agent's address). The customer object would have a matching ACL with their country code:

[ (Allow, 'Country:US', 'agent permissions') ]

If you are using traversal and it suits your application without making your head explode, you could also expose the customers under a tree that looks like

/customers/US/...
/customers/UK/...
/customers/CN/...
/customers/all/

 The US/UK/CN object would have the (Allow, 'Country:US', ...) ACL. The object /customers/US builds the partial SQLAlchemy query Session.query(Customer).filter_by(country_code='US'), passing it on to its __getitem__. Objects under /US/ only build on the filtered query and so are prevented from seeing the wrong customers. /customers/all/ is a similar object but it requires Backoffice permissions and does not filter the customers query.


Daniel Holth

unread,
Jun 19, 2012, 12:29:04 PM6/19/12
to pylons-...@googlegroups.com
On Tuesday, June 19, 2012 11:52:05 AM UTC-4, Robottaway wrote:
Wanted to chime in and say this, in case it isn't obvious. You need the ALL the permissions to be contry specific not just the view, otherwise you leave a security hole open where one can view only those in his country but can update anything.

As Daniel pointed out you could use the format like [(Allow, 'Agent:US', 'read'), (Allow, 'Agent:US', 'modify')] so that you can limit the Agent users to a given country.


The special DENY_ALL as the last entry in the ACL would be appropriate.
Reply all
Reply to author
Forward
0 new messages