Thanks for this great write-up, Luke.
On Thu, Jul 29, 2010 at 2:00 PM, Luke Tucker <[email protected]> wrote: > Hi, > > I wanted to give a heads up about the large group of security related > changes that are slated to come into the trunk in the near future. This > work impacts both geoserver and django and integrates work by aaime, groldan > and myself. > > The current state of these currently lives on this branch: > > http://github.com/ltucker/geonode/tree/security > > I strongly encourage anyone with an inclination to have a look, test it, > holler about anything that looks funny or there is any other objection. > This is especially true for anyone who has recently created new views or > heavily modified a view. I have tried to keep up with adding security to > views, but please double check if you can. > > Note: You will almost certainly need to rebuild your database and run a > build after pulling these changes -- also note that in a clean installation > it is necessary to create a django administrator between building and > running host for the first time. > > 10k ft. view > ============ > > * Geoserver authentication / authorization defers to django model > * Per object permissions on layers and maps > * Views check fine grained permissions > > 1k ft. view > =========== > > User interface > -------------- > > Providing you are are a user with rights to manage a layer or map, you will > see a link to 'Edit Permissions' in the 'Manage' section of the sidebar on > the detail page for the map or layer. From here you can assign levels of > access to anonymous users, all registered users or to specific users. This > interface is currently rudimentary currently -- additional work will follow > after these changes have been merged. Permissions are the union of > permissions from any category an accessing user belongs to -- you cannot > subtract permissions from a specific user. > > When layers or maps are created, they are assigned default permissions. > Administrative rights are granted to the creator. For maps, anyone can > read, registered users can read and modify. For layers, the data is > read-only for everyone. > > Checking Permission in views > ---------------------------- > > Checking permissions uses the standard django api for object permissions, > for example: > > request.user.has_perm('maps.change_layer', obj=some_layer) > > The current permissions available for maps are: > maps.view_map > maps.change_map > maps.delete_map > maps.change_map_permissions > > The current permissions available for layers are: > maps.view_layer > maps.change_layer > maps.delete_layer > maps.change_layer_permissions > > (here the prefix 'maps' refers to the django app label that they belong to) > > Please make appropriate checks for fine grained permissions in new views. > > Permission checking in templates > -------------------------------- > > Since django templates make it exceedingly annoying for both developers and > designers to do anything that requires arguments to a function, this is a > bit ugly. I included a template tag to ease this slightly -- the following > pattern is the best I've come up with: > > {% load geonode_auth %} > > ... > > {% has_obj_perm user layer "maps.delete_layer" as can_delete %} > ... > {% if can_delete %} > <a href="...">{% trans "Delete Layer" %}</a></li> > {% endif %} > > You could also place relevant permission values into the template context > if you know what you need. > > > How is geoserver affected ? > --------------------------- > > To obtain permission information, geoserver consults a special django view > /data/acls that returns a json structure describing the requesting user's > permissions. > > Geoserver is able to authenticate with django based on: > > * credentials the user obtained by logging into django (django session > cookie) > * credentials provided as HTTP basic auth which correspond to the > username/password of a django user > * credentials provided as HTTP basic auth which correspond to the > GEOSERVER_CREDENTIALS django setting (see below) > > Other changes of note > ===================== > > The development web server changes to paster > -------------------------------------------- > > This was changed in order to support multiple concurrent requests -- such > as a geoserver authentication request stemming from a django request to > geoserver. This change should be transparent when running paver host. If > you are running django and jetty separately, you can use the following > instead of django-admin runserver: > > paster serve --reload shared/dev-paste.ini > > > Special wacky geoserver_token file > ---------------------------------- > > The GEOSERVER_CREDENTIALS django setting now references a special file > called 'geoserver_token'. The first line of this file is used as a special > administrative password for use by django when administratively accessing > geoserver. A random string is placed in this file during a build to avoid > having a well known default. The credentials to not correspond to a geonode > login, but can be used to access geoserver as a superuser. so, like > settings.py, it's best to make sure access to this file is limited. > > This was chosen as an alternative to requiring the user to keep settings.py > synchronized with the username/password of a django administrative user > (since all geoserver auth otherwise derives from django auth). > > You can generate a new token by removing the geoserver_token file and > running: > > paver generate_geoserver_token > > Per-object permissions design > ----------------------------- > > Django does not currently provide an auth backend that supports per object > permissions (although it does provide an api for querying them) As such, > these changes include a custom auth backend and models that represent > per-object or "row-level" permissions. These are housed in the geonode.core > app models.py, auth.py and admin.py. The auth backend is rigged into > settings.py via the AUTHENTICATION_BACKENDS setting. > > > There are 3 model classes of note: > > * ObjectRole - a named bundle of django.contrib.auth.models.Permission > objects > * UserObjectRoleMapping: an assignment of an ObjectRole to a User in the > context of an object. > * GenericObjectRoleMapping: this represents assigning a role to an implicit > collection of users like 'all registered users' or 'all users' > > Users are assigned permissions on an object by being assigned a "role" > which points to a set of particular django.contrib.auth.model.Permission > objects. > > The current geonode logical security model for Maps and Layers allows > exactly one role to be assigned to a particular user for a particular object > -- representing a security "level" such as 'read-only' 'read-write' and > 'administrative'. These levels are explicitly represented by ObjectRole > objects populated in the initial_data fixture. > > Phew > ===== > > Okay, well please feel free to ask followup questions or point out anything > that I've missed. > > > Enjoy, > > - Luke > -- Sebastian Benthall OpenGeo - http://opengeo.org
