Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of the permission infrastructure in Pyramid?

I was finally able to make my first Pyramid test application with authentication and with management of group-level security. I read tons of pages of documentation and used this tutorial as a guide, and now everything seems to be working well: users can login and have access to different views depending on their groups.

Now I look at what I have done and all I can think of is "what is the point of all this complexity?".

My previous experiences with authentication were hand made (on Google App Engine and CherryPy) and were much more readable. The views had something as simple as if not 'admin' in user.groups: # 404. This is Pythonic, easy to read, it's where you expect it to be. I can understand it and anybody that understand Python can use it.

With Pyramid instead I need to spread the information across multiple files, write functions (like groupfinder) that will be called by I don't know who and store the returned values I don't know where.

I hope I am missing something, because I don't think that Pyramid has been designed by some sadistic mind that likes complex and unreadable code.

So here is my question: what is the advantage of spreading the information about what view is accessible to what user across many files (__init__.py, security.py, views.py, decorator attributes, resource tree objects, etc.) versus adding a simple if 'admin' in current_user.groups:?

I imagine some answer will be "you don't need to use it, but it's good to have it in case you want to use it". Well, hence my question. Why would I want to use it?

like image 886
stenci Avatar asked Apr 29 '17 04:04

stenci


1 Answers

Your question is rather loaded, in that it sounds like you've already decided this is complexity for no reason. I can assure you it isn't, it just may be that the kind of apps it's designed for allowing aren't things you personally have a need for. You might use it for a variety of advanced cases, we use prob 75% of it routinely, and are glad that if our clients decide we need to get really complex, there won't be an issue.

In brief:

The ACL system means you can use inheritance easily in creating row level permission (as opposed to table level), and these can be built up programmatically from a variety of sources.

The way ACLs are administered using rights means you can assign those rights any way you like, you aren't limited to a simple user/group/permission system.

The decoupling of authorization from authentication means you can change how the system determines if a request is an authenticated user. In my case we use a JWT authentication token system across distributed processes where authentication token decoding is handled in shared middleware and Pyramid's inner app uses the Remote User option to grab the user id from the wsgi env. We have one single auth and auth model in its own python package that multiple apps in a distributed service can share without issue. Testing difficult auth and auth scenarios is easy because we only have to stick the user and group principals in the WSGI env to properly simulated a logged in user.

The way views are protected by permission lookup on a right to a context makes decoupling action code from context code very elegant, and allows a lot of code re-use as well as (IMHO) the best security designs. It eliminates the possibility of all kinds of dumb mistakes that can compromise app. You don't even get to start executing the view code if the permission look up hasn't passed, and that permission lookup can grow as arbitrarily complex as you need with custom predicates. For example, my current app, a HIPAA compliant Lab software package has ludicrously complex role/right/perm rules and we were able to encapsulate them all in nicely reusable custom predicates.

The fact that the whole thing has the ZCA under the hood means we get a bomb-proof dependency injection system and can dynamically change components for testing, as well as create custom apps from base shared framework packages using DI and component based architectures instead of relying on inheritance schemes that get really nasty once they are too deep.

For historical background: Pyramid was originally BFG, which was a Repoze project by veteran Zope programmers. It came out of a coding community used for big and hard projects, a lot of large enterprise, NGO, and government projects where access rules are complex and are a critical feature. This is quite different from simple CMS building: Django, which was designed for newspaper sites, makes the simple cases very fast to build but is (IMHO) a pain for any complex permission system. (I have used the lot, CherryPY, Django,Pylons,Pyramid,Flask, etc)

If you need to build a large scale enterprise app in a manner where you are guaranteed not to hit the wall when the client comes back with some convoluted and difficult auth and auth needs, you're ok. You need to mix LDAP with JWT tokens and regular password logins but each one has different rules for certain URLS or perhaps for different origins of the request? No problem.

For my money, Pyramid + SQLAlchemy can't be beat for these kinds of thorny enterprise apps in Python, but there absolutely is a lot more to learn. It allows you to solve difficult problems with elegant software architecture, at the cost of more understanding and more boilerplate up front. As a project grows in scope, this cost diminishes relative to overall development cost. This is also why there aren't really out-of-the box auth and auth systems for Pyramid the way there are for Django. The chance of such a thing actually solving our problems here are almost nil, so it winds up being more work to try to extend such a thing than to just design it with the more advanced-programming friendly tools you get with Pyramid.

Hopefully that helps.

like image 198
Iain Duncan Avatar answered Nov 06 '22 16:11

Iain Duncan