-
Notifications
You must be signed in to change notification settings - Fork 1
GSIP 19
Allowing per layer security to complete the security offering started with service layer security Motivation Proposal Backwards Compatability Feedback Voting Links
Andrea Aime
This proposal will be implemented by 1.7.0-rc1 release
Under Discussion, In Progress, Completed, Rejected, Deferred
At the moment GeoServer only sports OGC service and service method security, many real world use cases need more granular control based on the data contents, and thus a layer based security. This proposal handles layer wide security only, per feature or per attribute security is out of the scope.
This project is to enhance the security subsystem in GeoServer to allow namespace-based and layer-based authorization for read/write access. The description of this work uses the term ‘layer’ to refer to either a GeoServer feature type or coverage.
Access permissions will be configurable by entries in a the GEOSERVERDATADIR/security/layers.properties property file, following the syntax already available for service level security:
namespace.layer.permission=ROLE_1[,ROLE_2][, ...]]
where:
- namespace indicates the name of the namespace. The wildcard * is used to indicate all namespaces (i.e. global scope).
- layer is the name of a feature type or coverage. The wildcard * is used to indicate all layers in the namespace.
- permission indicates the type of access permission *** ‘r’ - indicates read access permission *** ‘w’ - indicates write access permission
- ROLE#_ are the names of roles (defined in the user.properties file). The wildcard * is used to indicate the permission is applied to all users, including anonymous users.
Rules:
- Each entry must have a unique combination of namespace, layer, and permission values.
- If a permission at the global level is not specified, global
permissions are assumed to allow read/write access, i.e.
**.**.r=\* and/or **.**.w=**
** If a permission for a namespace is not specified, it inherits permissions from the global specification. - If a permission for a layer is not specified, it inherits permissions from it’s namespace specification.
- If a user belongs to multiple roles, the least restrictive permission they inherit will apply.
Once security is in place:
- the web administration tool, as well as all the demos, will only display namespaces and layers that the current user is allowed to see;
- all the OGC services will handle out only the layers the user can see, if the current user does not have write permission, all attempts at writing will fail
To ease up implementation, GeoServer will behave as if the unauthorized layers are unavailable or physically read only. This also allows for better security (throwing an exception about the layer not being accessible discloses the layer is there). Any attempt to access a secured layer with not enough rights will be logged for administrators to evaluate security threats and for debugging purposes.
The following entries demonstrate configuring GeoServer so that it is primarily a read-only server.
**.**.r=\*
**.**.w=NO*ONE
private.**.r=TRUSTED*ROLE
private.\*.w=TRUSTED*ROLE
topp.congress*district.w=STATE*LEGISLATORS
in this scenario here is the map of roles to permissions: | | private.* || topp.* || topp.congressdistrict || (all other namespaces) || | NOONE |(no access)_ | w | _ | w | | TRUSTEDROLE | r/w | r | r | r | | STATELEGISLATURES |*(no access)_ | r | r/w | r | | (all other users) | _(no access)_ | r | r | r |
The following entries demonstrate configuring GeoServer so that it is locked down.
**.**.r=TRUSTED*ROLE
**.**.w=TRUSTED*ROLE
topp.**.r=**
army.**.r=MILITAR*ROLE,TRUSTED*ROLE
army.**.w=MILITAR*ROLE,TRUSTED*ROLE
in this scenario here is the map of roles to permissions: || || topp.* || army.* || (all other namespaces) || | TRUSTEDROLE | r/w | r/w | r/w | | MILITARROLE | r | r/w | _ | | | r |(no access)_ | _(no access)_ |
The following entries demonstrate configuring GeoServer with global~~, namepace~~, and layer-level permissions.
**.**.r=TRUSTED*ROLE
**.**.w=NO*ONE
topp.**.r=**
topp.states.r=USA*CITIZEN*ROLE,LAND*MANAGER*ROLE,TRUSTED*ROLE
topp.states.w=NO*ONE
topp.poly*landmarks.w=LAND*MANAGER*ROLE
topp.militar*bases.r=MILITAR*ROLE
topp.militar*bases.w=MILITAR*ROLE
in this scenario here is the map of roles to permissions: || || topp.states || topp.polylandmarks || topp.militarbases || topp. || || | NO*ONE | w | r | _ | w | w | | TRUSTEDROLE | r | r | _ | r | r | | MILITARROLE | _ |r_ | r/w | r | _ | | USACITIZENROLE | r |r_ | _ | r |(no access)_ | | LANDMANAGERROLE | r | r/w | _ | r |(no access)_ | | (all other users) | *_ |*r_ | _ | r |(no access)_ |
Note: The topp.states.w=NO*ONE is not needed, because this permission would be inherited from the global level, i.e.
*.*.w=NO*ONE
```
### Example of an Invalid Configuration File
The following set of entries would not be valid because the namespace,
layer, permission combinations of the entries are not unique.
topp.state.rw=ROLE1 topp.state.rw=ROLE2,ROLE3
Proposal, implementation
------------------------
The current security integration uses an Acegi based filter to perform
authentication, Acegi then puts the result of the authentication in a
ThreadLocal variable that can be accessed using
`SecurityContextHolder.getContext ().getAuthentication ()`. This is
already leveraged by the dispatcher, that performs the necessary service
level checks.
The idea is to replicate the same checks at the catalog level, by
introducing a security wrapper as depicted in the following diagram:
![image](implementation.gif)
The catalog wrapper would forward all calls to the actual catalog, and
then filter out the results comparing them with the actual access level
of the current user, in particular:
* by removing all layers that the user is not authorized to see
* by wrapping FeatureTypeInfo if the user is not authorized to write
them (coverages are at the moment read only, so this does not apply)
This leaves most of the GeoServer code completely security unaware,
making development and maintenance easier compared to a solution that
would move the security checks onto the services themselves.
The catch is, in order to wrap the catalog, it must be split into an
interface and an implementation. This is possible, and it’s going to be
introduced along with the new configuration proposal, so this one will
be implemented as soon as the new configuration proposal lands on trunk
Relationship with service layer security
----------------------------------------
GeoServer 1.6.0+ sports service level security as described in the
[user guide](http://geoserver.org/display/GEOSDOC/2.5) Security
subsystem .
The data level security builds on top of it, reusing user and role
definitions found in `$GEOSERVER*DATA*DIR/security/users.properties`.
Each request will be subject to both security checks, according to the
following workflow:
* the user gets authenticated using Acegi integration (at the moment,
either form or HTTP basic authentication)
* the service level security gets checked by the dispatcher, if access
is denied, the request ends
* the service will attempt to access the catalog, each of those
attempts will be subjected to data level security restrictions
So, to sum up, in order to successfully execute an OGC service call the
user will have to be allowed to execute the requested service method and
to access the data specified in the request.
Feedback
--------
This section should contain feedback provided by PSC members who may
have a problem with the proposal.
Backwards Compatibility
-----------------------
The proposal has not backwards compatibility issues, the default
layers.properties file will be empty, meaning all layers can be accessed
by everyone.
Voting
------
Andrea Aime: +1
Alessio Fabiani: +1
Justin Deoliveira: +1
Jody Garnett: +1
Saul Farber:
Rob Atkinson:
Links
-----
[JIRA Task](http://jira.codehaus.org/browse/GEOS-1969)
©2020 Open Source Geospatial Foundation