currently I am looking implementing access control in Django. I've read about the built-in permission, but it does not takes care per object basis. For example, I want permissions like "Only the creator can delete his own items". So I read about django-guardian. Then again, after thinking about it, it may be difficult to manage and check if constraints ever change.
I look at the next popular permission management app called django-rules. This seems to suit what I require. However, I believe django-rules requires a model instance to be involved (hence object level) i.e if I require a simple view like "member's area", it does not perform this function.
This has led me to think about using both the contrib's permission for the latter scenarios and django-rules for the former. My question here, is how easy will it be to manage both permission frameworks?. For instance, I have different groups of users. I am worried about overlapping scenarios whereby the admin added a particular permission in the admin system (to allow access to a view), thinking that should suffice but turns out to be bounded by constraints set by the rules.
I believe this is a common case and I humbly seek your advices and recommendations based on your experiences.
If you're doing this through Django admin site, you can override methods such as has_delete_permission(). These get request and object as arguments, so you can use it to set up rules like "User X can delete only his own objects".
Related
I'm struggling at building a website with Django. On that website, I want to have a lot of information about TV shows. I want my user to be able to insert and modify information. The information needs to be moderated, a change should not be published before being accepted by a moderator.
I came across django-moderation as a solution to that aspect.
My user will log into another instance of django-admin, with different user rights.
I'm adding django-guardian to deal with per-object permissions.
I'm lost a bit lost now. I think I'll find how to interface all those things, and it will work in a few weeks after reading all the docs, making all the mistakes, etc...
I am wondering thou if the architecture makes sense, if are software components I am missing out on.
Thank you for your consideration.
edit : BTW, working with django 1.7 on python 3.4
django-moderation looks interesting, I haven't used it. There's not a lot of activity in the project, but it's active. I think it will suit the use-case you have in mind. I considered django-guardian recently for a project and rejected it in favour of extending tastypie's authorizations. I think my use case was a bit different, I needed to maintain constraints on foreign key relationships that were hard to express with django-guardian. If you only intend to allow or reject read/write permissions and don't need to validate anything beyond rudimentary data points, it will do a good job (in that case, use Django's model validators).
In general: Django has a wide assortment of easily included apps. in general: if you can solve it with pip install, do so.
I have objects in my system with relations to owners and collaborators and now I need to add permissions on viewing these objects. Currently if the user is the owner or listed as a collaborator they can see the object. I have that logic encapsulated already but it seems the "proper" way would be to use a row level permission system and assign these users permissions. However that becomes more complicated when it comes to assigning and removing permissions and also makes viewing more expensive as it has to look up permissions in the database rather then relying on data that is already being accessed. I have been looking into django-guardian and it seems like overkill right now.
Check out django-logical-rules. Rules are written in python and you can pass existing objects to a rule, so their isn't necessarily a db hit... although I would recommend caching. Rules can be easily integrated with generic views and accessible with a template tag.
Background
I have a backoffice that manages information from various sources. Part of the information is in a database that the backoffice can access directly, and part of it is managed by accessing web services. Such services usually provides CRUD operations plus paged searches.
There is an access control system that determines what actions a user is allowed to perform. The decision of whether the user can perform some action is defined by authorization rules that depend on the underlying data model. E.g. there is a rule that allows a user to edit a resource if she is the owner of that resource, where the owner is a column in the resources table. There are other rules such as "a user can edit a resource if that resource belongs to an organization and the user is a member of that organization".
This approach works well when the domain model is directly available to the access control system. Its main advantage is that it avoids replicating information that is already present in the domain model.
When the data to be manipulated comes from a Web service, this approach starts causing problems. I can see various approaches that I will discuss below.
Implementing the access control in the service
This approach seems natural, because otherwise someone could bypass access control by calling the service directly. The problem is that the backoffice has no way to know what actions are available to the user on a particular entity. Because of that, it is not possible to disable options that are unavailable to the user, such as an "edit" button.
One could add additional operations to the service to retrieve the authorized actions on a particular entity, but it seems that we would be handling multiple responsibilities to the service.
Implementing the access control in the backoffice
Assuming that the service trusts the backoffice application, one could decide to implement the access control in the backoffice. This seems to solve the issue of knowing which actions are available to the user. The main issue with this approach is that it is no longer possible to perform paged searches because the service will now return every entity that matches, instead of entities that match and that the user is also authorized to see.
Implementing a centralized access control service
If access control was centralized in a single service, everybody would be able to use it to consult access rights on specific entities. However, we would lose the ability to use the domain model to implement the access control rules. There is also a performance issue with this approach, because in order to return lists of search results that contain only the authorized results, there is no way to filter the database query with the access control rules. One has to perform the filtering in memory after retrieving all of the search results.
Conclusion
I am now stuck because none of the above solutions is satisfactory. What other approaches can be used to solve this problem? Are there ways to work around the limitations of the approaches I proposed?
One could add additional operations to the service to retrieve the
authorized actions on a particular entity, but it seems that we would
be handling multiple responsibilities to the service.
Not really. Return a flags field/property from the web service for each record/object that can then be used to pretty up the UI based on what the user can do. The flags are based off the same information that is used for access control that the service is accessing anyway. This also makes the service able to support a browser based AJAX access method and skip the backoffice part in the future for added flexibility.
Distinguish between the components of your access control system and implement each where it makes sense.
Access to specific search results in a list should be implemented by the service that reads the results, and the user interface never needs to know about the results the user doesn't have access to. If the user may or may not edit or interact in other ways with data the user is allowed to see, the service should return that data with flags indicating what the user may do, and the user interface should reflect those flags. Service implementing those interactions should not trust the user interface, it should validate the user has access when the service is called. You may have to implement the access control logic in multiple database queries.
Access to general functionality the user may or may not have access to independant of data should again be controlled by the service implementing that functionality. That service should compute access through a module that is also exposed as a service so that the UI can respect the access rules and not try to call services the user does not have access to.
I understand my response is very late - 3 years late. It's worth shedding some new light on an age-old problem. Back in 2011, access-control was not as mature as it is today. In particular, there is a new model, abac along with a standard implementation, xacml which make centralized authorization possible.
In the OP's question, the OP writes the following re centralized access control:
Implementing a centralized access control service
If access control was centralized in a single service, everybody would be able to use it to consult access rights on specific entities. However, we would lose the ability to use the domain model to implement the access control rules. There is also a performance issue with this approach, because in order to return lists of search results that contain only the authorized results, there is no way to filter the database query with the access control rules. One has to perform the filtering in memory after retrieving all of the search results.
The drawbacks that the OP mentions may have been true in a home-grown access control system, in RBAC, or in ACL. But they are no longer true in abac and xacml. Let's take them one by one.
The ability to use the domain model to implement the access control rules
With attribute-based access control (abac) and the eXtensible Access Control Markup Language (xacml), it is possible to use the domain model and its properties (or attributes) to write access control policies. For instance, if the use case is that of a doctor wishing to view medical records, the domain model would define the Doctor entity with its properties (location, unit, and so on) as well as the Medical Record entity. A rule in XACML could look as follows:
A user with the role==doctor can do the action==view on an object of type==medical record if and only if the doctor.location==medicalRecord.location.
A user with the role==doctor can do the action==edit on an object of type==medical record if and only if the doctor.id==medicalRecord.assignedDoctor.id
One of the key benefits of XACML is precisely to mirror closely the business logic and the domain model of your applications.
Performance issue - the ability to filter items from a db
In the past, it was indeed impossible to create filter expressions. This meant that, as the OP points out, one would have to retrieve all the data first and then filter the data. That would be an expensive task. Now, with XACML, it is possible to achieve reverse querying. The ability to run a reverse query is to create a question of the type "What medical record can Alice view?" instead of the traditional binary question "Can Alice view medical records #123?".
The response of a reverse query is a filter condition which can be converted into a SQL statement, for instance in this scenario SELECT id FROM medicalRecords WHERE location=Chicago assuming of course that the doctor is based in Chicago.
What does the architecture look like?
One of the key benefits of a centralized access control service (also known as externalized authorization) is that you can apply the same consistent authorization logic to your presentation tier, business tier, APIs, web services, and even databases.
I'm trying to configure a wiki to allow a two staged approval process. The basic work flow requires something like:
A group of users submits a short form
After admin approval, a larger form becomes available to the group
The group submits the larger form
After admin approval, the page (filled by the form) becomes public
I've been looking at TikiWiki and MediaWiki for a while trying to configure each to get even close to this model, but I'm having some problems.
With TikiWiki, it seems like the approval stage should be a transition, either changing the group permissions to allow access to a new tracker or changing the form category to close one form and open the other, but I haven't been able to nail down the permissions for that configuration.
With MediaWiki, the main problem seems to be that the back-end was not made to have complex permissions. I've been using SMWHalo along with SemanticForms to construct this, but I can't find anything like Tikiwiki's transitions for changing the permissions for either the group or the form automatically.
I'm a bit new to Wiki development and I know that there are a lot of options for wiki frameworks, so I'm asking for suggestions for a good work flow for this product. My goal is to only start actually touching the framework code to make the final adjustments and not to start off modifying an already well developed code base.
You should really ask yourself why you want this and why you want this in a wiki.
A Wiki's main advantage is being quick and easy and thus encouraging to the user. Adding approval stages will discourage users to participate. The hardest part in any wiki is not preventing vandalism or false information. The hardest part is to encourage participation.
If you really need a difficult approval workflow you might want to look at CMS systems. AFAIK typo3 has something like this built in.
If really you want to go with a wiki and an approval process, for DokuWiki you could have a look a the publish plugin: http://www.dokuwiki.org/plugin:publish
The FlaggedRevs extension to MediaWiki adds a basic permissions workflow:
http://www.mediawiki.org/wiki/Extension:FlaggedRevs
However, it's geared more at controlling changes to existing pages, not adding entirely new ones. You could set it up to create new pages as drafts and defaulting the public view to show only approved versions, but it sounds like you want to hide unapproved versions entirely, which would require some extra hacking (and, as Andreas says, kind of defeats the point of a wiki in the first place).
I am developing a Django web application with a suite of steel design tools for structural engineers. There will be a database table of inputs for each design tool, and each row of each table will correspond to a particular design condition to be "solved." The users may work solely or in groups. Each user needs to have ongoing access to his own work so that designs can be refined, copied and adapted, and so that reports can be created whenever convenient, usually at the end of a project when hard copy documentation will be needed. The database contents must then be available over any number of sessions occurring over periods measured in months or even years for a given design project.
When there is a group of users, typically all associated with a given design office, it will probably be acceptable for them all to have joint and mutual access to each other's work. The application supports routine engineering production activities, not innovative intellectual property work, and in-house privacy is not the norm in the industry anyway. However, the work absolutely must be shielded from prying eyes outside of the group. Ideally, each group would have one or more superusers authorized to police the membership of the group. Probably the main tool they would need would be the ability to remove a member from the group, discontinuing his access privileges. This would be a user group superuser and would not be the same as a superuser on the site side.
For convenient access, each row of each database table will be associated with a project number/project name pair that will be unique for a given company deploying a user or user group. A different company could easily choose to use a duplicate project number, and even could choose a duplicate project name, so discriminating exactly which database rows belong to a given user (or group) will probably have to be tracked in a separate related "ownership list" table for each user (or group).
It is anticipated (hoped) that, eventually, several hundred users (or user groups) associated with different (and often competing) companies will solve tens of thousands of design conditions for thousands of projects using these tools.
So, here are my questions:
First, is there any point in trying to salvage much of anything from the Django contrib.auth code? As I perceive it, contrib.auth is designed for authentication and access control that is suitable for the blogosphere and web journalism, but that doesn't support fine-grained control of access to "content."
Second, is there any available template, pattern, example, strategy or design advice I could apply to this problem?
django-authority: Documentation, code on GitHub