Initial issue description at https://github.com/geoserver/geofence/issues/222
A GeoServer instance may have multiple chained authentication services, providing different role semantics.
As a use case, there is an instance having
- an auth service:
- Access via authkey
- Accessing with two different authkey, the same user may be belonging to different groups (with different privs)
- The geoserver auth class selects the proper role and set it into the request object
- In this case GeoFence should use that role in the rule filtering –> we need the “Use GEOSERVER roles to get authorizations” and pass to GeoFence the roles selected by the auth plugin.
- a geonode auth service:
- Access via credentials/authkey
- The credentials uniquely identify the user, which may belong to one or more roles
- GeoFence should use all the roles in the rule filtering and merge all the privs
- Unsetting “Use GEOSERVER roles to get authorizations” will make the geofence client create a filter without any role set, so GeoFence will retrieve all the roles associated to the user, get the privs associate to each role and merge them.
Role filtering
In order to make the first auth service work, we must enable “Use GEOSERVER roles to get authorizations”.
Please note that such an option requires a list of role names (a text field labeled “comma delimited list of mutually exclusive roles for authorization”): the GeoFenceAccessManager will only consider a role passed in the request instance only if it’s in the role name list.
This behaviour was too limiting in some cases where the role names are not static so, as reported in a previous comment and documented in GEOS-10420, an improvement was implemented in order to use the first of the roles passed in the request object (so the role name is dynamic and not pre-determined).
Please also note that the previous implementation would only use the last role matching in the intersection role list provided in the “comma delimited list of mutually exclusive roles for authorization” and the role list in the request.
There are several limitations and misleading behaviours in this implementation:
- Using “*”, only the first role found is passed in the GeoFence filter
- it’s not said the ordering of the roles in the request is fixed and that we are consistently taking the right role
- usually “*” is meant to take “all elements found”, but in this case it means “any one element”
- at the moment GeoFence accepts filtering with a single role
Proposed solution
If “Use GEOSERVER roles to get authorizations” is selected and we have “*” as authorization groups, we will pass all the provided roles to GeoFence.
- in djam case, we’ll be passing the djam role plus any other general user role (such as “ROLE_AUTHENTICATED” or similar)
- in geonode case, we’ll be passing all the roles which GeoFence would otherwise retrieve from the
GroupRoleProvider (which should be the very same list).
This would solve the misleading behaviour described above.
The RuleFilter should allow for multiple roles.
Changing the bean could be a risk for back compatibility: consider implementing this change by packing all the role names in a single comma separated textin order to not change the DTO. In this case we should enforce some ordering of the role names, in order to preserve the instance hash.
The setRuleFilterUserOrRole method should be able to set multiple roles into RuleFilter
The logic should be changed in order to use multiple roles passed in the filter.
Pls note the the changes in RuleReaderServiceImpl may require extensive changes: at the moment GeoServer can request authorization either by user or by role.
- If auth by user is requested, GeoFence will retrieve all the rules for the user and for the assigned roles found in the DB.
- If auth by role is requested, GeoFence will only apply rules related to the group.
This behaviour should be improved (yet being backcompatible)
Other changes
“Use GEOSERVER roles to get authorizations” should read “User authentication roles to get authorizations”
|